1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001-2003 Red Hat, Inc.
*
* Created by David Woodhouse <[email protected]>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
* $Id: gcthread.c,v 1.3 2005/01/22 16:01:12 lunn Exp $
*
*/
#include <linux/kernel.h>
#include "nodelist.h"
//#include <cyg/kernel/kapi.h> prife
#if defined(CYGOPT_FS_JFFS2_GCTHREAD)
#define GC_THREAD_FLAG_TRIG 1
#define GC_THREAD_FLAG_STOP 2
#define GC_THREAD_FLAG_HAS_EXIT 4
#if 0
static cyg_thread_entry_t jffs2_garbage_collect_thread;
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
/* Wake up the thread */
D1(printk("jffs2_garbage_collect_trigger\n"));
cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG);
}
void
jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
RT_ASSERT(c);
RT_ASSERT(!sb->s_gc_thread_handle);
cyg_flag_init(&sb->s_gc_thread_flags);
cyg_mutex_init(&sb->s_lock);
D1(printk("jffs2_start_garbage_collect_thread\n"));
/* Start the thread. Doesn't matter if it fails -- it's only an
* optimisation anyway */
cyg_thread_create(CYGNUM_JFFS2_GC_THREAD_PRIORITY,
jffs2_garbage_collect_thread,
(unsigned long)c,"jffs2 gc thread",
(void*)sb->s_gc_thread_stack,
sizeof(sb->s_gc_thread_stack),
&sb->s_gc_thread_handle,
&sb->s_gc_thread);
cyg_thread_resume(sb->s_gc_thread_handle);
}
void
jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
RT_ASSERT(sb->s_gc_thread_handle);
D1(printk("jffs2_stop_garbage_collect_thread\n"));
/* Stop the thread and wait for it if necessary */
cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP);
D1(printk("jffs2_stop_garbage_collect_thread wait\n"));
cyg_flag_wait(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_HAS_EXIT,
CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR);
// Kill and free the resources ... this is safe due to the flag
// from the thread.
cyg_thread_kill(sb->s_gc_thread_handle);
cyg_thread_delete(sb->s_gc_thread_handle);
cyg_mutex_destroy(&sb->s_lock);
cyg_flag_destroy(&sb->s_gc_thread_flags);
}
static void
jffs2_garbage_collect_thread(unsigned long data)
{
struct jffs2_sb_info *c=(struct jffs2_sb_info *)data;
struct super_block *sb=OFNI_BS_2SFFJ(c);
cyg_flag_value_t flag;
cyg_mtab_entry *mte;
D1(printk("jffs2_garbage_collect_thread START\n"));
while(1) {
flag=cyg_flag_timed_wait(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_TRIG|GC_THREAD_FLAG_STOP,
CYG_FLAG_WAITMODE_OR| CYG_FLAG_WAITMODE_CLR,
cyg_current_time()+
CYGNUM_JFFS2_GS_THREAD_TICKS);
if (flag & GC_THREAD_FLAG_STOP)
break;
D1(printk("jffs2: GC THREAD GC BEGIN\n"));
mte=cyg_fs_root_lookup((cyg_dir *) sb->s_root);
CYG_ASSERT(mte, "Bad mount point");
cyg_fs_lock(mte, mte->fs->syncmode);
if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
printf("No space for garbage collection. "
"Aborting JFFS2 GC thread\n");
break;
}
cyg_fs_unlock(mte, mte->fs->syncmode);
D1(printk("jffs2: GC THREAD GC END\n"));
}
D1(printk("jffs2_garbage_collect_thread EXIT\n"));
cyg_flag_setbits(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT);
}
#endif
rt_uint32_t cyg_current_time(void)
{
return 0;
}
static void
jffs2_garbage_collect_thread(unsigned long data);
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
/* Wake up the thread */
D1(printk("jffs2_garbage_collect_trigger\n"));
rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_TRIG);
}
static struct rt_thread gc_thread;
void
jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
cyg_mtab_entry *mte;
int result;
RT_ASSERT(c);
//RT_ASSERT(!sb->s_gc_thread_handle);
mte=(cyg_dir *) sb->s_root;
RT_ASSERT(mte);
rt_event_init(&sb->s_gc_thread_flags, "gc_event", RT_IPC_FLAG_FIFO);
rt_mutex_init(&sb->s_lock, "gc_mutex", RT_IPC_FLAG_FIFO);
// rt_mutex_init(&mte->fs->syncmode, "fs_lock", RT_IPC_FLAG_FIFO);
D1(printk("jffs2_start_garbage_collect_thread\n"));
/* Start the thread. Doesn't matter if it fails -- it's only an
* optimisation anyway */
result = rt_thread_init(&sb->s_gc_thread,
"jffs2_gc_thread",
jffs2_garbage_collect_thread,
(void *)c,
(void*)sb->s_gc_thread_stack,
sizeof(sb->s_gc_thread_stack),
CYGNUM_JFFS2_GC_THREAD_PRIORITY,
CYGNUM_JFFS2_GC_THREAD_TICKS
);
if (result != RT_EOK) {
rt_thread_startup(&sb->s_gc_thread);
/* how to deal with the following filed? */
/* sb->s_gc_thread_handle; */
}
}
void
jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
{
struct super_block *sb=OFNI_BS_2SFFJ(c);
cyg_mtab_entry *mte;
rt_uint32_t e;
//RT_ASSERT(sb->s_gc_thread_handle);
D1(printk("jffs2_stop_garbage_collect_thread\n"));
/* Stop the thread and wait for it if necessary */
rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_STOP);
D1(printk("jffs2_stop_garbage_collect_thread wait\n"));
rt_event_recv(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_HAS_EXIT,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, &e);
// Kill and free the resources ... this is safe due to the flag
// from the thread.
rt_thread_detach(&sb->s_gc_thread);
rt_sem_detach(&sb->s_lock);
rt_event_detach(&sb->s_gc_thread_flags);
}
static void
jffs2_garbage_collect_thread(unsigned long data)
{
struct jffs2_sb_info *c=(struct jffs2_sb_info *)data;
struct super_block *sb=OFNI_BS_2SFFJ(c);
cyg_mtab_entry *mte;
rt_uint32_t flag = 0;
D1(printk("jffs2_garbage_collect_thread START\n"));
while(1) {
rt_event_recv(&sb->s_gc_thread_flags,
GC_THREAD_FLAG_TRIG | GC_THREAD_FLAG_STOP,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
cyg_current_time() + CYGNUM_JFFS2_GS_THREAD_TICKS,
&flag);
if (flag & GC_THREAD_FLAG_STOP)
break;
D1(printk("jffs2: GC THREAD GC BEGIN\n"));
mte=(cyg_dir *) sb->s_root;
RT_ASSERT(mte != NULL);
// rt_mutex_take(&mte->fs->syncmode, RT_WAITING_FOREVER);
if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
printf("No space for garbage collection. "
"Aborting JFFS2 GC thread\n");
break;
}
// rt_mutex_release(&mte->fs->syncmode);
D1(printk("jffs2: GC THREAD GC END\n"));
}
D1(printk("jffs2_garbage_collect_thread EXIT\n"));
rt_event_send(&sb->s_gc_thread_flags,GC_THREAD_FLAG_HAS_EXIT);
}
#endif
|