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 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 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 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 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 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