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