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
 
128
struct emcorelib_header* get_library_ext(uint32_t identifier, uint32_t minversion,
129
                                         uint32_t maxversion, enum library_sourcetype sourcetype,
130
                                         void* source, struct scheduler_thread* owner)
131
{
132
    int i;
133
    int version = minversion - 1;
134
    struct library_handle* h;
135
    struct library_handle* best = NULL;
136
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
137
    for (h = library_list_head; h; h = h->next)
138
        if (h->lib->identifier == identifier &&
139
            h->lib->version > version && h->lib->version <= maxversion)
140
        {
141
            best = h;
142
            version = h->lib->version;
143
            break;
144
        }
145
    if (!best)
146
    {
466 theseven 147
        switch (sourcetype)
148
        {
149
        case LIBSOURCE_RAM_ALLOCED:
150
        {
151
            best = (struct library_handle*)execimage(source, false);
152
            break;
153
        }
154
 
155
        case LIBSOURCE_RAM_NEEDCOPY:
156
        {
157
            best = (struct library_handle*)execimage(source, true);
158
            break;
159
        }
160
 
161
#ifdef HAVE_BOOTFLASH
162
        case LIBSOURCE_BOOTFLASH:
163
        {
164
            int size = bootflash_filesize((char*)source);
165
            if (size <= 0) break;
166
            void* buffer = memalign(0x10, size);
167
            if (!buffer) break;
168
            if (bootflash_read((char*)source, buffer, 0, size) != size)
169
            {
170
                free(buffer);
171
                break;
172
            }
173
            best = (struct library_handle*)execimage(buffer, false);
174
            break;
175
        }
176
#endif
177
 
178
#ifdef HAVE_STORAGE
179
        case LIBSOURCE_FILESYSTEM:
180
        {
181
            int fd = file_open((char*)source, O_RDONLY);
182
            if (fd <= 0) break;
183
            int size = filesize(fd);
184
            if (size <= 0)
185
            {
186
                close(fd);
187
                break;
188
            }
189
            void* buffer = memalign(0x10, size);
190
            if (!buffer)
191
            {
192
                close(fd);
193
                break;
194
            }
195
            if (read(fd, buffer, size) != size)
196
            {
197
                free(buffer);
198
                close(fd);
199
                break;
200
            }
201
            close(fd);
202
            best = (struct library_handle*)execimage(buffer, false);
203
            break;
204
        }
205
#endif
206
        }
207
        if (!best)
208
        {
209
            mutex_unlock(&library_mutex);
210
            return NULL;
211
        }
465 theseven 212
    }
213
    for (i = 0; i < ARRAYLEN(best->users); i++)
214
        if (best->users[i] == NULL)
215
        {
216
            best->users[i] = owner;
217
            mutex_unlock(&library_mutex);
218
            return best->lib;
219
        }
220
    if (best->moreusers)
221
        for (i = 0; i < best->moreusers_size / 4; i++)
222
            if (h->moreusers[i] == NULL)
223
                {
224
                    h->moreusers[i] = owner;
225
                    mutex_unlock(&library_mutex);
226
                    return best->lib;
227
                }
228
    void* newalloc = realloc(best->moreusers, best->moreusers_size + 64);
229
    if (!newalloc)
230
    {
231
        mutex_unlock(&library_mutex);
232
        return NULL;
233
    }
234
    best->moreusers = (void**)newalloc;
235
    best->moreusers[best->moreusers_size / 4] = owner;
236
    best->moreusers_size += 64;
237
    mutex_unlock(&library_mutex);
238
    return best->lib;
239
}
240
 
241
struct emcorelib_header* get_library(uint32_t identifier, uint32_t minversion, uint32_t maxversion,
242
                                     enum library_sourcetype sourcetype, void* source)
243
{
244
    return get_library_ext(identifier, minversion, maxversion, sourcetype, source, current_thread);
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
}