Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / exec / allocabs.c
blob5bc8544e3a20a299490d4fc2e1f4f9590d155af4
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Allocate memory at address
6 Lang: english
7 */
8 #include <exec/alerts.h>
9 #include <exec/execbase.h>
10 #include "memory.h"
11 #include <exec/memory.h>
12 #include <exec/memheaderext.h>
13 #include <proto/exec.h>
15 /*****************************************************************************
17 NAME */
19 AROS_LH2(APTR, AllocAbs,
21 /* SYNOPSIS */
22 AROS_LHA(ULONG, byteSize, D0),
23 AROS_LHA(APTR, location, D1),
25 /* LOCATION */
26 struct ExecBase *, SysBase, 34, Exec)
28 /* FUNCTION
29 Allocate some memory from the system memory pool at a given address.
31 INPUTS
32 byteSize - Number of bytes you want to get
33 location - Where you want to get the memory
35 RESULT
36 A pointer to some memory including the requested bytes or NULL if
37 the memory couldn't be allocated
39 NOTES
41 EXAMPLE
43 BUGS
45 SEE ALSO
46 FreeMem()
48 INTERNALS
50 ******************************************************************************/
52 AROS_LIBFUNC_INIT
54 struct MemHeader *mh;
55 APTR ret = NULL;
57 /* Zero bytes requested? May return everything ;-). */
58 if(!byteSize)
59 return NULL;
61 /* Protect the memory list from access by other tasks. */
62 Forbid();
64 /* Loop over MemHeader structures */
65 ForeachNode(&SysBase->MemList, mh)
67 if (mh->mh_Lower <= location && mh->mh_Upper > location)
68 break;
71 /* If no header was found which matched the requirements, just give up. */
72 if (!mh->mh_Node.ln_Succ)
74 Permit();
75 return NULL;
78 /* If the header is managed, let the mager handle the request. */
79 if (mh->mh_Attributes & MEMF_MANAGED)
81 struct MemHeaderExt *mhe = (struct MemHeaderExt *)mh;
83 if (mhe->mhe_AllocAbs)
84 ret = mhe->mhe_AllocAbs(mhe, byteSize, location);
86 else
88 struct MemChunk *p1, *p2, *p3, *p4;
90 /* Align size to the requirements */
91 byteSize += (IPTR)location&(MEMCHUNK_TOTAL - 1);
92 byteSize = (byteSize + MEMCHUNK_TOTAL-1) & ~(MEMCHUNK_TOTAL-1);
94 /* Align the location as well */
95 location=(APTR)((IPTR)location & ~(MEMCHUNK_TOTAL-1));
97 /* Start and end(+1) of the block */
98 p3=(struct MemChunk *)location;
99 p4=(struct MemChunk *)((UBYTE *)p3+byteSize);
102 The free memory list is only single linked, i.e. to remove
103 elements from the list I need the node's predessor. For the
104 first element I can use freeList->mh_First instead of a real
105 predecessor.
107 p1 = (struct MemChunk *)&mh->mh_First;
108 p2 = p1->mc_Next;
110 /* Follow the list to find a chunk with our memory. */
111 while (p2 != NULL)
113 #if !defined(NO_CONSISTENCY_CHECKS)
115 Do some constistency checks:
116 1. All MemChunks must be aligned to
117 MEMCHUNK_TOTAL.
118 2. The end (+1) of the current MemChunk
119 must be lower than the start of the next one.
121 if( ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
122 ||( (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
123 &&p2->mc_Next!=NULL))
124 Alert(AN_MemCorrupt|AT_DeadEnd);
125 #endif
127 /* Found a chunk that fits? */
128 if((UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p4&&p2<=p3)
130 /* Check if there's memory left at the end. */
131 if((UBYTE *)p2+p2->mc_Bytes!=(UBYTE *)p4)
133 /* Yes. Add it to the list */
134 p4->mc_Next = p2->mc_Next;
135 p4->mc_Bytes = (UBYTE *)p2+p2->mc_Bytes-(UBYTE *)p4;
136 p2->mc_Next = p4;
139 /* Check if there's memory left at the start. */
140 if(p2!=p3)
141 /* Yes. Adjust the size */
142 p2->mc_Bytes=(UBYTE *)p3-(UBYTE *)p2;
143 else
144 /* No. Skip the old chunk */
145 p1->mc_Next=p2->mc_Next;
147 /* Adjust free memory count */
148 mh->mh_Free-=byteSize;
150 /* Return the memory */
151 ret = p3;
152 break;
154 /* goto next chunk */
156 p1=p2;
157 p2=p2->mc_Next;
161 Permit();
163 return ret;
165 AROS_LIBFUNC_EXIT
166 } /* AllocAbs */