Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
429 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
677 theseven 6
//    This file is part of emCORE.
429 theseven 7
//
677 theseven 8
//    emCORE is free software: you can redistribute it and/or
429 theseven 9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
677 theseven 13
//    emCORE is distributed in the hope that it will be useful,
429 theseven 14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
677 theseven 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
429 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "malloc.h"
26
#include "libc/tlsf/tlsf.h"
27
 
28
 
812 theseven 29
extern char _poolstart;   // These aren't chars at all, but gcc complains about void types being
565 theseven 30
extern char _poolend;     // used here, and we only need the address, so just make it happy...
429 theseven 31
 
32
struct mutex malloc_mutex;
33
tlsf_pool global_mallocpool;
34
 
35
 
36
void* malloc(size_t size)
37
{
38
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
39
    void* ptr = tlsf_malloc(global_mallocpool, size + 4);
812 theseven 40
    if (ptr)
41
    {
42
        size = tlsf_block_size(ptr);
43
        *((struct scheduler_thread**)(ptr + size - 4)) = current_thread;
44
    }
45
    DEBUGF("malloc(%08X) => %08X (thread: %08X)", size, ptr, current_thread);
429 theseven 46
    mutex_unlock(&malloc_mutex);
47
    return ptr;
48
}
49
 
50
void* memalign(size_t align, size_t size)
51
{
52
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
53
    void* ptr = tlsf_memalign(global_mallocpool, align, size + 4);
812 theseven 54
    if (ptr)
55
    {
56
        size = tlsf_block_size(ptr);
57
        *((struct scheduler_thread**)(ptr + size - 4)) = current_thread;
58
    }
59
    DEBUGF("memalign(%X, %08X) => %08X (thread: %08X)", align, size, ptr, current_thread);
429 theseven 60
    mutex_unlock(&malloc_mutex);
61
    return ptr;
62
}
63
 
625 theseven 64
void* realign(void* ptr, size_t align, size_t size)
429 theseven 65
{
66
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
67
    size_t oldsize = tlsf_block_size(ptr);
571 theseven 68
    struct scheduler_thread* owner = *((struct scheduler_thread**)(ptr + oldsize - 4));
812 theseven 69
    void* ptr_new = tlsf_realign(global_mallocpool, ptr, align, size + 4);
70
    if (ptr_new)
570 theseven 71
    {
812 theseven 72
        size = tlsf_block_size(ptr_new);
73
        *((struct scheduler_thread**)(ptr_new + size - 4)) = owner;
570 theseven 74
    }
812 theseven 75
    DEBUGF("realign(%08X, %X, %08X) => %08X (old size: %08X, owner: %08X, thread: %08X)",
76
           ptr, align, size, ptr_new, owner, current_thread);
429 theseven 77
    mutex_unlock(&malloc_mutex);
812 theseven 78
    return ptr_new;
429 theseven 79
}
80
 
625 theseven 81
void* realloc(void* ptr, size_t size)
82
{
83
    return realign(ptr, 4, size);
84
}
85
 
429 theseven 86
void reownalloc(void* ptr, struct scheduler_thread* owner)
87
{
88
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
89
    size_t size = tlsf_block_size(ptr);
812 theseven 90
    DEBUGF("reownalloc(%08X, %08X) (size: %08X, old owner: %08X, thread: %08X)",
818 theseven 91
           ptr, owner, size, *((struct scheduler_thread**)(ptr + size - 4)), current_thread);
429 theseven 92
    *((struct scheduler_thread**)(ptr + size - 4)) = owner;
93
    mutex_unlock(&malloc_mutex);
94
}
95
 
96
void free(void* ptr)
97
{
98
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
812 theseven 99
    size_t size = tlsf_block_size(ptr);
100
    DEBUGF("free(%08X) (size: %08X, owner: %08X, thread: %08X)", ptr, size,
101
           *((struct scheduler_thread**)(ptr + size - 4)), current_thread);
429 theseven 102
    tlsf_free(global_mallocpool, ptr);
103
    mutex_unlock(&malloc_mutex);
104
}
105
 
106
void free_if_thread(void* ptr, size_t size, int used, void* owner)
107
{
818 theseven 108
    if (*((void**)(ptr + size - 4)) == owner) free(ptr);
429 theseven 109
}
110
 
111
void free_all_of_thread(struct scheduler_thread* owner)
112
{
113
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
812 theseven 114
    DEBUGF("free_all_of_thread(%08X) (thread: %08X)", owner, current_thread);
429 theseven 115
    tlsf_walk_heap(global_mallocpool, free_if_thread, owner);
116
    mutex_unlock(&malloc_mutex);
117
}
118
 
565 theseven 119
void malloc_walk(void (*walker), void* user)
120
{
121
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
122
    tlsf_walk_heap(global_mallocpool, walker, user);
123
    mutex_unlock(&malloc_mutex);
124
}
125
 
818 theseven 126
void malloc_lock()
127
{
128
    mutex_lock(&malloc_mutex, TIMEOUT_BLOCK);
129
}
130
 
131
void malloc_unlock()
132
{
133
    mutex_unlock(&malloc_mutex);
134
}
135
 
429 theseven 136
void malloc_init()
137
{
138
    mutex_init(&malloc_mutex);
436 theseven 139
    global_mallocpool = tlsf_create(&_poolstart, &_poolend - &_poolstart);
429 theseven 140
}