00001
00007
00008
00009 #include <kernel.h>
00010 #include <platform.h>
00011 #include <memory.h>
00012
00013 extern void *end;
00014
00020 syscall freemem(void *pmem)
00021 {
00022 struct memblock *block, *next, *prev;
00023 irqmask ps;
00024 ulong top, size;
00025
00026
00027 block = (struct memblock *)pmem;
00028
00029 block--;
00030
00031
00032 ASSERT( (ulong)block >= (ulong)minheap );
00033 ASSERT( (ulong)block < (ulong)platform.maxaddr );
00034
00035 ps = disable();
00036
00037
00038 if ( (block->next != block) || (block->length == 0) )
00039 {
00040 restore(ps);
00041 return SYSERR;
00042 }
00043
00044 size = block->length;
00045
00046
00047
00048 prev = &freelist;
00049 next = freelist.next;
00050 while ( (next != NULL) && (next < block) )
00051 {
00052 prev = next;
00053 next = next->next;
00054 }
00055
00056
00057
00058
00059
00060 if (prev == &freelist) { top = NULL; }
00061 else { top = (ulong)prev + prev->length; }
00062
00063
00064
00065 if ( ( top > (ulong)block )
00066 || ( (next != NULL) && ((ulong)block + size) > (ulong)next ) )
00067 {
00068 restore(ps);
00069 return SYSERR;
00070 }
00071
00072
00073 freelist.length += block->length;
00074
00075
00076
00077 if ( top == (ulong)block )
00078 {
00079
00080 prev->length += size;
00081
00082
00083 block->next = NULL;
00084 block->length = 0;
00085
00086
00087 block = prev;
00088 }
00089 else
00090 {
00091
00092 block->next = next;
00093 prev->next = block;
00094 }
00095
00096
00097 if ( (ulong)((ulong)block + block->length) == (ulong)next )
00098 {
00099
00100 block->length += next->length;
00101 block->next = next->next;
00102
00103
00104 next->next = NULL;
00105 next->length = 0;
00106 }
00107
00108 restore(ps);
00109 return OK;
00110 }