3 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #define UMEM_HEAP_ADDR 0x800000 // MEMORY HEAP is placed at 8MB address
30 #define UMEM_MALLOC_MAGIC 0xebc9 // MALLOC STRUCTURE signature
32 #define UMEM_MALLOC_STATE_FREE 0xaa // MEMORY is FREE at moment
33 #define UMEM_MALLOC_STATE_USED 0xcc // MEMORY is USED at moment
40 } __attribute__ ((__packed__
)) malloc_t
;
43 void *addr
; /* heap structure is covered by own heap structure address */
44 void *first
; /* first malloc structure */
45 void *last
; /* last malloc structure - usefully for calculate memory usage */
46 void *curr
; /* current malloc structure */
47 } __attribute__ ((__packed__
)) heap_t
;
49 static heap_t
*heap
; /* heap structure of memory */
50 static MUTEX_CREATE (mutex_umalloc
);
51 static MUTEX_CREATE (mutex_ufree
);
53 void *umalloc (proc_t
*proc
, size_t size
)
58 mutex_lock (&mutex_umalloc
);
60 unsigned malloc_len
= sizeof (malloc_t
); /* check malloc structure size */
61 unsigned need_alloc
= 0;
63 /* let's find new or free malloc structure in memory */
64 malloc_t
*malloc
= (malloc_t
*) heap
->first
;
67 //DPRINT (DBG_MM | DBG_UMEM, "malloc: 0x%x\n", malloc);
70 DPRINT (DBG_MM
| DBG_UMEM
, "!malloc");
75 if (malloc
->magic
!= UMEM_MALLOC_MAGIC
) {
76 DPRINT (DBG_MM
| DBG_UMEM
, "malloc->magic != UMEM_MALLOC_MAGIC");
81 if (malloc
->state
== UMEM_MALLOC_STATE_USED
) { /* It's OK */
82 DPRINT (DBG_MM
| DBG_UMEM
, "malloc->state == UMEM_MALLOC_STATE_USED");
84 malloc
= (malloc_t
*) malloc
->next
;
88 /* we've found FREE memory block, at moment it is not used */
89 if (malloc
->state
== UMEM_MALLOC_STATE_FREE
) {
90 /* read next malloc structure, right behind free block */
91 malloc_t
*next
= (malloc_t
*) malloc
;
93 DPRINT (DBG_MM
| DBG_UMEM
, "malloc->state == UMEM_MALLOC_STATE_FREE");
96 if (next
->magic
!= UMEM_MALLOC_MAGIC
) {
97 DPRINT (DBG_MM
| DBG_UMEM
, "2: next->magic != UMEM_MALLOC_MAGIC (%x/%x)", next
->magic
, UMEM_MALLOC_MAGIC
);
101 /* unused memory size between current and next block */
102 long diff
= ((unsigned) (next
->next
) - (unsigned) (malloc
));
104 /* does needed block fit in unused one ? */
105 if (diff
>= (unsigned) size
+ malloc_len
) {
108 /* we have to join all continuous free blocks into one and match last (next) */
110 malloc
->next
= (malloc_t
*) ((void *) malloc
+ size
+ malloc_len
);
112 if (diff
> size
+ malloc_len
) {
114 unsigned mnext
= (unsigned) next
->next
;
116 malloc_t
*n
= (malloc_t
*) ((void *) malloc
+ size
+ malloc_len
);
118 n
->magic
= UMEM_MALLOC_MAGIC
;
119 n
->state
= UMEM_MALLOC_STATE_FREE
;
120 n
->next
= (void *) mnext
;
124 //malloc = (char *) next;
126 //heap->curr = mnext;
127 //kprintf ("DIFF: %d - 0x%x / 0x%x\n", diff - malloc_len, mnext, n);
131 if (next
->state
== UMEM_MALLOC_STATE_USED
)
134 if (next
->state
== UMEM_MALLOC_STATE_USED
)
137 if (next
->state
!= UMEM_MALLOC_STATE_FREE
)
140 next
= (malloc_t
*) next
->next
;
146 unsigned diff = (unsigned) ((void *) next - (void *) malloc);
148 DPRINT (DBG_MM | DBG_UMEM, "diff: %d", diff);
151 malloc = (malloc_t *) malloc->next;
161 malloc
= (malloc_t
*) malloc
->next
;
164 if (need_alloc
== 1) {
165 /* when old malloc structures are full, let's grab new block of memory */
168 malloc
->magic
= UMEM_MALLOC_MAGIC
;
170 malloc
->next
= (void *) ((void *) malloc
+ malloc_len
+ size
);
172 heap
->curr
= malloc
->next
;
175 malloc
->state
= UMEM_MALLOC_STATE_USED
;
179 /* calculate size of process image (binary file) */
180 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
182 /* save last malloc structure pointer to heap */
183 if ((unsigned) heap
->curr
> (unsigned) heap
->last
)
184 heap
->last
= heap
->curr
;
187 unsigned s
= proc
->heap
;
188 for (l
= s
; l
< (unsigned) ((char *) malloc
+ malloc_len
+ size
); l
+= 0x1000) {
190 page_mmap (proc
->task
->page_cover
, (void *) proc
->heap
+p
, (void *) proc
->heap
+p
+ 0x1000, 0, 1);
192 //kprintf ("OD: 0x%x DO: 0x%x | 0x%x | 0x%x\n", (void *) proc->heap + p, (void *) proc->heap + 0x1000 + p, s, size);
193 proc
->heap
+= 0x1000;
196 mutex_unlock (&mutex_umalloc
);
197 //kprintf ("MEM: 0x%x - %d - 0x%x\n", ((void *) malloc + malloc_len + p), size, p);
198 return (void *) ((void *) malloc
+ malloc_len
+ p
);
201 void ufree (proc_t
*proc
, void *ptr
)
206 mutex_lock (&mutex_ufree
);
208 /* calculate size of process image (binary file) */
209 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
211 /* we need find malloc structure - it could be risk working with lower memory address */
212 malloc_t
*malloc
= (void *) ((void *) ptr
- sizeof (malloc_t
) - p
);
214 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
215 if (malloc
->magic
!= UMEM_MALLOC_MAGIC
) {
216 DPRINT (DBG_MM
| DBG_UMEM
, "free: malloc->magic != UMEM_MALLOC_MAGIC");
220 /* is this memory block our ? */
221 if (malloc
->proc
!= proc
) {
222 DPRINT (DBG_MM
| DBG_UMEM
, "free: malloc->proc != proc");
226 if (malloc
->state
== UMEM_MALLOC_STATE_FREE
) {
227 DPRINT (DBG_MM
| DBG_UMEM
, "free () - memory is FREE - double free !");
231 if (malloc
->state
!= UMEM_MALLOC_STATE_USED
) {
232 DPRINT (DBG_MM
| DBG_UMEM
, "malloc->state != UMEM_MALLOC_STATE_USED");
236 /* match malloc as FREE */
237 malloc
->state
= UMEM_MALLOC_STATE_FREE
;
240 mutex_unlock (&mutex_ufree
);
243 void *urealloc (proc_t
*proc
, void *ptr
, size_t size
)
249 return umalloc (proc
, size
);
256 /* calculate size of process image (binary file) */
257 unsigned p
= (unsigned) palign ((void *) (proc
->end
- proc
->start
));
259 /* we need find malloc structure - it could be risk working with lower memory address */
260 malloc_t
*malloc
= (void *) ((char *) ptr
- sizeof (malloc_t
) - p
);
262 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
263 if (malloc
->magic
!= UMEM_MALLOC_MAGIC
) {
264 DPRINT (DBG_MM
| DBG_UMEM
, "urealloc: malloc->magic != UMEM_MALLOC_MAGIC");
268 int s
= (int) (malloc
->next
- ptr
) + p
;
273 char *ptr_new
= umalloc (proc
, size
);
281 /* copy old memory block to new one (-p because ptr and ptr_new got virtual mapped address) */
282 memcpy (ptr_new
- p
, ptr
- p
, s
);
289 /* free all memory blocks allocated by process */
290 unsigned ufree_proc (proc_t
*proc
)
298 for (malloc
= (malloc_t
*) heap
->first
; malloc
->magic
== UMEM_MALLOC_MAGIC
; malloc
= (malloc_t
*) malloc
->next
)
299 if (malloc
->proc
== proc
)
300 if (malloc
->state
== UMEM_MALLOC_STATE_USED
)
301 malloc
->state
= UMEM_MALLOC_STATE_FREE
;
308 /* calculate used memory by process */
309 unsigned umem_used_proc (proc_t
*proc
)
317 for (malloc
= (malloc_t
*) heap
->first
; malloc
->magic
== UMEM_MALLOC_MAGIC
; malloc
= (malloc_t
*) malloc
->next
)
318 if (malloc
->proc
== proc
)
319 if (malloc
->state
== UMEM_MALLOC_STATE_USED
)
320 used
+= (int) ((unsigned) malloc
->next
- (unsigned) malloc
);
327 /* calculate used memory from all apps */
328 unsigned umem_used ()
336 for (malloc
= (malloc_t
*) heap
->first
; malloc
->magic
== UMEM_MALLOC_MAGIC
; malloc
= (malloc_t
*) malloc
->next
)
337 if (malloc
->state
== UMEM_MALLOC_STATE_USED
)
338 used
+= (int) ((unsigned) malloc
->next
- (unsigned) malloc
);
345 unsigned umem_init ()
347 heap
= (heap_t
*) UMEM_HEAP_ADDR
;
349 /* we rather clear heap structure */
350 heap
->addr
= (void *) heap
;
351 heap
->first
= (void *) ((void *) heap
+ sizeof (heap_t
)); /* first malloc structure should be right behind heap structure */
352 heap
->last
= heap
->first
; /* last malloc structure - it is first at init */
353 heap
->curr
= heap
->first
; /* point to first malloc structure - well, it is clear and not used yet */