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;
67
    mutex_unlock(&library_mutex);
68
    return handle;
69
}
70
 
71
int library_unload(struct library_handle* lib)
72
{
73
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
74
    int i;
75
    bool found = false;
76
    struct library_handle* h;
77
    for (h = library_list_head; h; h = h->next)
78
        if (h == lib)
79
        {
80
            found = true;
81
            break;
82
        }
83
    if (!found)
84
    {
85
        mutex_unlock(&library_mutex);
86
        return -1;
87
    }
88
    for (i = 0; i < ARRAYLEN(lib->users); i++)
89
        if (lib->users[i])
90
        {
91
            mutex_unlock(&library_mutex);
92
            return -2;
93
        }
94
    if (lib->moreusers)
95
        for (i = 0; i < lib->moreusers_size / 4; i++)
96
            if (lib->moreusers[i])
97
            {
98
                mutex_unlock(&library_mutex);
99
                return -2;
100
            }
101
    if (lib->lib->shutdownfunc && lib->lib->shutdownfunc() < 0)
102
    {
103
        mutex_unlock(&library_mutex);
104
        return -3;
105
    }
106
    if (library_list_head == lib) library_list_head = lib->next;
107
    else
108
        for (h = library_list_head; h; h = h->next)
109
            if (h == lib)
110
            {
111
                h->next = lib->next;
112
                break;
113
            }
114
    library_release_all_of_thread((struct scheduler_thread*)lib);
115
#ifdef HAVE_STORAGE
116
    close_all_of_process((struct scheduler_thread*)lib);
117
    closedir_all_of_process((struct scheduler_thread*)lib);
118
#endif
119
#ifdef HAVE_BUTTON
120
    button_unregister_all_of_thread((struct scheduler_thread*)lib);
121
#endif
122
    free_all_of_thread((struct scheduler_thread*)lib);
123
    mutex_unlock(&library_mutex);
124
    return 0;
125
}
126
 
127
struct emcorelib_header* get_library_ext(uint32_t identifier, uint32_t minversion,
128
                                         uint32_t maxversion, enum library_sourcetype sourcetype,
129
                                         void* source, struct scheduler_thread* owner)
130
{
131
    int i;
132
    int version = minversion - 1;
133
    struct library_handle* h;
134
    struct library_handle* best = NULL;
135
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
136
    for (h = library_list_head; h; h = h->next)
137
        if (h->lib->identifier == identifier &&
138
            h->lib->version > version && h->lib->version <= maxversion)
139
        {
140
            best = h;
141
            version = h->lib->version;
142
            break;
143
        }
144
    if (!best)
145
    {
146
        mutex_unlock(&library_mutex);
147
        return NULL;
148
    }
149
    for (i = 0; i < ARRAYLEN(best->users); i++)
150
        if (best->users[i] == NULL)
151
        {
152
            best->users[i] = owner;
153
            mutex_unlock(&library_mutex);
154
            return best->lib;
155
        }
156
    if (best->moreusers)
157
        for (i = 0; i < best->moreusers_size / 4; i++)
158
            if (h->moreusers[i] == NULL)
159
                {
160
                    h->moreusers[i] = owner;
161
                    mutex_unlock(&library_mutex);
162
                    return best->lib;
163
                }
164
    void* newalloc = realloc(best->moreusers, best->moreusers_size + 64);
165
    if (!newalloc)
166
    {
167
        mutex_unlock(&library_mutex);
168
        return NULL;
169
    }
170
    best->moreusers = (void**)newalloc;
171
    best->moreusers[best->moreusers_size / 4] = owner;
172
    best->moreusers_size += 64;
173
    mutex_unlock(&library_mutex);
174
    return best->lib;
175
}
176
 
177
struct emcorelib_header* get_library(uint32_t identifier, uint32_t minversion, uint32_t maxversion,
178
                                     enum library_sourcetype sourcetype, void* source)
179
{
180
    return get_library_ext(identifier, minversion, maxversion, sourcetype, source, current_thread);
181
}
182
 
183
int release_library_ext(struct emcorelib_header* lib, struct scheduler_thread* owner)
184
{
185
    int i;
186
    int rc = -2;
187
    struct library_handle* h;
188
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
189
    for (h = library_list_head; h; h = h->next)
190
        if (h->lib == lib)
191
        {
192
            rc = -1;
193
            for (i = 0; i < ARRAYLEN(h->users); i++)
194
                if (h->users[i] == owner)
195
                {
196
                    h->users[i] = NULL;
197
                    rc = 0;
198
                    break;
199
                }
200
            if (rc && h->moreusers)
201
                for (i = 0; i < h->moreusers_size / 4; i++)
202
                    if (h->moreusers[i] == owner)
203
                        {
204
                            h->moreusers[i] = NULL;
205
                            rc = 0;
206
                            break;
207
                        }
208
            break;
209
        }
210
    mutex_unlock(&library_mutex);
211
    return rc;
212
}
213
 
214
int release_library(struct emcorelib_header* lib)
215
{
216
    return release_library_ext(lib, current_thread);
217
}
218
 
219
int library_release_all_of_thread(struct scheduler_thread* thread)
220
{
221
    mutex_lock(&library_mutex, TIMEOUT_BLOCK);
222
    int i;
223
    int released = 0;
224
    struct library_handle* h;
225
    for (h = library_list_head; h; h = h->next)
226
    {
227
        for (i = 0; i < ARRAYLEN(h->users); i++)
228
            if (h->users[i] == thread)
229
            {
230
                h->users[i] = NULL;
231
                released++;
232
            }
233
        if (h->moreusers)
234
            for (i = 0; i < h->moreusers_size / 4; i++)
235
                if (h->moreusers[i] == thread)
236
                    {
237
                        h->moreusers[i] = NULL;
238
                        released++;
239
                    }
240
    }
241
    mutex_unlock(&library_mutex);
242
    return released;
243
}