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