- Give PCI controllers lower unit numbers than legacy controllers.
[cake.git] / rom / exec / allocpooled.c
blob07b470247bc903ce1a789a261d0428f80b4b43ab
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Allocate memory in a pool.
6 Lang: english
7 */
8 #include "exec_intern.h"
9 #include <aros/libcall.h>
10 #include "memory.h"
12 #include "exec_debug.h"
13 #ifndef DEBUG_AllocPooled
14 # define DEBUG_AllocPooled 0
15 #endif
16 #undef DEBUG
17 #if DEBUG_AllocPooled
18 # define DEBUG 1
19 #endif
20 #include <aros/debug.h>
21 #undef kprintf
23 /*****************************************************************************
25 NAME */
26 #include <exec/memory.h>
27 #include <proto/exec.h>
29 AROS_LH2(APTR, AllocPooled,
31 /* SYNOPSIS */
32 AROS_LHA(APTR, poolHeader, A0),
33 AROS_LHA(ULONG, memSize, D0),
35 /* LOCATION */
36 struct ExecBase *, SysBase, 118, Exec)
38 /* FUNCTION
39 Allocate memory out of a private memory pool.
41 INPUTS
42 poolHeader - Handle of the memory pool
43 memSize - Number of bytes you want to get
45 RESULT
46 A pointer to the number of bytes you wanted or NULL if the memory
47 couldn't be allocated
49 NOTES
51 EXAMPLE
53 BUGS
55 SEE ALSO
56 CreatePool(), DeletePool(), FreePooled()
58 INTERNALS
60 ******************************************************************************/
62 AROS_LIBFUNC_INIT
64 struct ProtectedPool *pool = (struct ProtectedPool *)poolHeader;
65 APTR ret = NULL;
67 D(bug("AllocPooled $%lx memsize $%lx by \"%s\"\n", poolHeader, memSize, SysBase->ThisTask->tc_Node.ln_Name));
69 if (pool->pool.Requirements & MEMF_SEM_PROTECTED)
71 ObtainSemaphore(&pool->sem);
74 /* If the memSize is bigger than the ThreshSize allocate seperately. */
75 if(memSize > pool->pool.ThreshSize)
77 struct Block *bl;
78 ULONG size;
80 /* Get enough memory for the memory block including the header. */
81 size = memSize + BLOCK_TOTAL;
82 bl = (struct Block *)AllocMem(size, pool->pool.Requirements & ~MEMF_SEM_PROTECTED);
84 /* No memory left */
85 if(bl == NULL)
86 goto done;
88 /* Initialize the header */
89 bl->Size = size;
91 /* Add the block to the BlockList */
92 AddHead((struct List *)&pool->pool.BlockList,(struct Node *)&bl->Node);
94 /* Set pointer to allocated memory */
95 ret = (UBYTE *)bl + BLOCK_TOTAL;
97 else
99 struct MemHeader *mh;
101 /* Follow the list of MemHeaders */
102 mh = (struct MemHeader *)pool->pool.PuddleList.mlh_Head;
103 for(;;)
105 /* Are there no more MemHeaders? */
106 if(mh->mh_Node.ln_Succ==NULL)
108 /* Get a new one */
109 mh = (struct MemHeader *)
110 AllocMem(pool->pool.PuddleSize + MEMHEADER_TOTAL,
111 pool->pool.Requirements & ~MEMF_SEM_PROTECTED);
113 /* No memory left? */
114 if(mh == NULL)
115 goto done;
117 /* Initialize new MemHeader */
118 mh->mh_First = (struct MemChunk *)((UBYTE *)mh + MEMHEADER_TOTAL);
119 mh->mh_First->mc_Next = NULL;
120 mh->mh_First->mc_Bytes = pool->pool.PuddleSize;
121 mh->mh_Lower = mh->mh_First;
122 mh->mh_Upper = (UBYTE *)mh->mh_First+pool->pool.PuddleSize;
123 mh->mh_Free = pool->pool.PuddleSize;
125 /* And add it to the list */
126 AddHead((struct List *)&pool->pool.PuddleList, (struct Node *)&mh->mh_Node);
127 /* Fall through to get the memory */
129 /* Try to get the memory */
130 ret = Allocate(mh, memSize);
132 /* Got it? */
133 if(ret != NULL)
135 /* If this is not the first MemHeader and it has some free space, move it to the head */
136 if (mh->mh_Node.ln_Pred != NULL && mh->mh_Free > 32)
138 Remove((struct Node *)mh);
139 AddHead((struct List *)&pool->pool.PuddleList, (struct Node *)&mh->mh_Node);
142 break;
145 /* No. Try next MemHeader */
146 mh = (struct MemHeader *)mh->mh_Node.ln_Succ;
148 /* Allocate does not clear the memory! */
149 if(pool->pool.Requirements & MEMF_CLEAR)
151 ULONG *p= (ULONG *)ret;
153 /* Round up (clearing longs is faster than just bytes) */
154 memSize = (memSize + sizeof(ULONG) - 1) / sizeof(ULONG);
156 /* NUL the memory out */
157 while(memSize--)
158 *p++=0;
162 done:
163 if (pool->pool.Requirements & MEMF_SEM_PROTECTED)
165 ReleaseSemaphore(&pool->sem);
168 /* Everything fine */
169 return ret;
171 AROS_LIBFUNC_EXIT
173 } /* AllocPooled */