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