Subversion Repositories freemyipod

Rev

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

Rev Author Line No. Line
465 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
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
//
13
//    emCORE is distributed in the hope that it will be useful,
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
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "library.h"
26
#include "malloc.h"
27
#include "execimage.h"
28
#include "thread.h"
29
#ifdef HAVE_STORAGE
30
#include "file.h"
31
#include "dir.h"
32
#endif
33
#ifdef HAVE_BOOTFLASH
34
#include "bootflash.h"
35
#endif
36
#ifdef HAVE_BUTTON
37
#include "button.h"
38
#endif
39
 
40
 
682 theseven 41
static struct library_handle* library_list_head;
42
static struct mutex library_mutex;
465 theseven 43
 
44
 
45
struct library_handle* library_register(void* image, struct emcorelib_header* header)
46
{
47
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
48
    struct library_handle* h;
49
    for (h = library_list_head; h; h = h->next)
50
        if (h->lib->identifier == header->identifier && h->lib->version == header->version)
51
        {
52
            mutex_unlock(&library_mutex);
53
            return NULL;
54
        }
468 theseven 55
    if ((header->setupfunc && header->setupfunc() < 0)
56
     || (header->initfunc && header->initfunc() < 0))
465 theseven 57
    {
58
        mutex_unlock(&library_mutex);
59
        return NULL;
60
    }
61
    struct library_handle* handle = (struct library_handle*)malloc(sizeof(struct library_handle));
62
    memset(handle, 0, sizeof(struct library_handle));
814 theseven 63
    reownalloc(handle, OWNER_TYPE(OWNER_LIBRARY, handle));
64
    reownalloc(image, OWNER_TYPE(OWNER_LIBRARY, handle));
465 theseven 65
    handle->next = library_list_head;
66
    handle->lib = header;
67
    handle->alloc = image;
466 theseven 68
    library_list_head = handle;
465 theseven 69
    mutex_unlock(&library_mutex);
70
    return handle;
71
}
72
 
489 theseven 73
int library_unload(struct emcorelib_header* lib)
465 theseven 74
{
75
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
76
    int i;
77
    bool found = false;
78
    struct library_handle* h;
489 theseven 79
    struct library_handle* prev;
465 theseven 80
    for (h = library_list_head; h; h = h->next)
489 theseven 81
        if (h->lib == lib)
465 theseven 82
        {
83
            found = true;
84
            break;
85
        }
567 theseven 86
        else prev = h;
465 theseven 87
    if (!found)
88
    {
89
        mutex_unlock(&library_mutex);
90
        return -1;
91
    }
489 theseven 92
    for (i = 0; i < ARRAYLEN(h->users); i++)
93
        if (h->users[i])
465 theseven 94
        {
95
            mutex_unlock(&library_mutex);
96
            return -2;
97
        }
489 theseven 98
    if (h->moreusers)
99
        for (i = 0; i < h->moreusers_size / 4; i++)
100
            if (h->moreusers[i])
465 theseven 101
            {
102
                mutex_unlock(&library_mutex);
103
                return -2;
104
            }
489 theseven 105
    if (lib->shutdownfunc && lib->shutdownfunc() < 0)
465 theseven 106
    {
107
        mutex_unlock(&library_mutex);
108
        return -3;
109
    }
489 theseven 110
    if (library_list_head == h) library_list_head = h->next;
567 theseven 111
    else prev->next = h->next;
814 theseven 112
    library_release_all_of_thread(OWNER_TYPE(OWNER_LIBRARY, h));
465 theseven 113
#ifdef HAVE_STORAGE
814 theseven 114
    close_all_of_process(OWNER_TYPE(OWNER_LIBRARY, h));
115
    closedir_all_of_process(OWNER_TYPE(OWNER_LIBRARY, h));
465 theseven 116
#endif
117
#ifdef HAVE_BUTTON
814 theseven 118
    button_unregister_all_of_thread(OWNER_TYPE(OWNER_LIBRARY, h));
465 theseven 119
#endif
814 theseven 120
    free_all_of_thread(OWNER_TYPE(OWNER_LIBRARY, h));
465 theseven 121
    mutex_unlock(&library_mutex);
122
    return 0;
123
}
124
 
467 theseven 125
struct emcorelib_header* get_library_ext(uint32_t identifier, uint32_t version,
126
                                         enum library_sourcetype sourcetype, void* source,
127
                                         struct scheduler_thread* owner)
465 theseven 128
{
129
    int i;
130
    struct library_handle* h;
467 theseven 131
    struct library_handle* lib = NULL;
465 theseven 132
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
133
    for (h = library_list_head; h; h = h->next)
134
        if (h->lib->identifier == identifier &&
467 theseven 135
            h->lib->minversion <= version && h->lib->version >= version)
465 theseven 136
        {
467 theseven 137
            lib = h;
465 theseven 138
            break;
139
        }
467 theseven 140
    if (!lib)
465 theseven 141
    {
466 theseven 142
        switch (sourcetype)
143
        {
144
        case LIBSOURCE_RAM_ALLOCED:
145
        {
467 theseven 146
            lib = (struct library_handle*)execimage(source, false);
466 theseven 147
            break;
148
        }
149
 
150
        case LIBSOURCE_RAM_NEEDCOPY:
151
        {
467 theseven 152
            lib = (struct library_handle*)execimage(source, true);
466 theseven 153
            break;
154
        }
155
 
156
#ifdef HAVE_BOOTFLASH
157
        case LIBSOURCE_BOOTFLASH:
158
        {
159
            int size = bootflash_filesize((char*)source);
160
            if (size <= 0) break;
161
            void* buffer = memalign(0x10, size);
162
            if (!buffer) break;
163
            if (bootflash_read((char*)source, buffer, 0, size) != size)
164
            {
165
                free(buffer);
166
                break;
167
            }
467 theseven 168
            lib = (struct library_handle*)execimage(buffer, false);
466 theseven 169
            break;
170
        }
171
#endif
172
 
173
#ifdef HAVE_STORAGE
174
        case LIBSOURCE_FILESYSTEM:
175
        {
176
            int fd = file_open((char*)source, O_RDONLY);
177
            if (fd <= 0) break;
178
            int size = filesize(fd);
179
            if (size <= 0)
180
            {
181
                close(fd);
182
                break;
183
            }
184
            void* buffer = memalign(0x10, size);
185
            if (!buffer)
186
            {
187
                close(fd);
188
                break;
189
            }
190
            if (read(fd, buffer, size) != size)
191
            {
192
                free(buffer);
193
                close(fd);
194
                break;
195
            }
196
            close(fd);
467 theseven 197
            lib = (struct library_handle*)execimage(buffer, false);
466 theseven 198
            break;
199
        }
200
#endif
201
        }
489 theseven 202
        if (lib && (lib->lib->identifier != identifier
203
                 || lib->lib->minversion > version && lib->lib->version < version))
467 theseven 204
            lib = NULL;
205
        if (!lib)
466 theseven 206
        {
207
            mutex_unlock(&library_mutex);
208
            return NULL;
209
        }
465 theseven 210
    }
467 theseven 211
    for (i = 0; i < ARRAYLEN(lib->users); i++)
212
        if (lib->users[i] == NULL)
465 theseven 213
        {
467 theseven 214
            lib->users[i] = owner;
465 theseven 215
            mutex_unlock(&library_mutex);
467 theseven 216
            return lib->lib;
465 theseven 217
        }
467 theseven 218
    if (lib->moreusers)
219
        for (i = 0; i < lib->moreusers_size / 4; i++)
465 theseven 220
            if (h->moreusers[i] == NULL)
221
                {
222
                    h->moreusers[i] = owner;
223
                    mutex_unlock(&library_mutex);
467 theseven 224
                    return lib->lib;
465 theseven 225
                }
467 theseven 226
    void* newalloc = realloc(lib->moreusers, lib->moreusers_size + 64);
465 theseven 227
    if (!newalloc)
228
    {
229
        mutex_unlock(&library_mutex);
230
        return NULL;
231
    }
821 theseven 232
    reownalloc(newalloc, OWNER_TYPE(OWNER_LIBRARY, lib));
467 theseven 233
    lib->moreusers = (void**)newalloc;
234
    lib->moreusers[lib->moreusers_size / 4] = owner;
235
    lib->moreusers_size += 64;
465 theseven 236
    mutex_unlock(&library_mutex);
467 theseven 237
    return lib->lib;
465 theseven 238
}
239
 
467 theseven 240
struct emcorelib_header* get_library(uint32_t identifier, uint32_t version,
465 theseven 241
                                     enum library_sourcetype sourcetype, void* source)
242
{
467 theseven 243
    return get_library_ext(identifier, version, sourcetype, source, current_thread);
465 theseven 244
}
245
 
246
int release_library_ext(struct emcorelib_header* lib, struct scheduler_thread* owner)
247
{
248
    int i;
249
    int rc = -2;
250
    struct library_handle* h;
251
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
252
    for (h = library_list_head; h; h = h->next)
253
        if (h->lib == lib)
254
        {
255
            rc = -1;
256
            for (i = 0; i < ARRAYLEN(h->users); i++)
257
                if (h->users[i] == owner)
258
                {
259
                    h->users[i] = NULL;
260
                    rc = 0;
261
                    break;
262
                }
263
            if (rc && h->moreusers)
264
                for (i = 0; i < h->moreusers_size / 4; i++)
265
                    if (h->moreusers[i] == owner)
266
                        {
267
                            h->moreusers[i] = NULL;
268
                            rc = 0;
269
                            break;
270
                        }
271
            break;
272
        }
273
    mutex_unlock(&library_mutex);
274
    return rc;
275
}
276
 
277
int release_library(struct emcorelib_header* lib)
278
{
279
    return release_library_ext(lib, current_thread);
280
}
281
 
282
int library_release_all_of_thread(struct scheduler_thread* thread)
283
{
284
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
285
    int i;
286
    int released = 0;
287
    struct library_handle* h;
288
    for (h = library_list_head; h; h = h->next)
289
    {
290
        for (i = 0; i < ARRAYLEN(h->users); i++)
291
            if (h->users[i] == thread)
292
            {
293
                h->users[i] = NULL;
294
                released++;
295
            }
296
        if (h->moreusers)
297
            for (i = 0; i < h->moreusers_size / 4; i++)
298
                if (h->moreusers[i] == thread)
299
                    {
300
                        h->moreusers[i] = NULL;
301
                        released++;
302
                    }
303
    }
304
    mutex_unlock(&library_mutex);
305
    return released;
306
}