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