This stack check implementation leverages the compiler's profiling (gcc -p)
[linux-2.6.git] / drivers / dump / dump_rle.c
1 /*
2  * RLE Compression functions for kernel crash dumps.
3  *
4  * Created by: Matt Robinson (yakker@sourceforge.net)
5  * Copyright 2001 Matt D. Robinson.  All rights reserved.
6  *
7  * This code is released under version 2 of the GNU GPL.
8  */
9
10 /* header files */
11 #include <linux/config.h>
12 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <linux/fs.h>
15 #include <linux/file.h>
16 #include <linux/init.h>
17 #include <linux/dump.h>
18
19 /*
20  * Name: dump_compress_rle()
21  * Func: Compress a DUMP_PAGE_SIZE (hardware) page down to something more
22  *       reasonable, if possible.  This is the same routine we use in IRIX.
23  */
24 static u16
25 dump_compress_rle(const u8 *old, u16 oldsize, u8 *new, u16 newsize)
26 {
27         u16 ri, wi, count = 0;
28         u_char value = 0, cur_byte;
29
30         /*
31          * If the block should happen to "compress" to larger than the
32          * buffer size, allocate a larger one and change cur_buf_size.
33          */
34
35         wi = ri = 0;
36
37         while (ri < oldsize) {
38                 if (!ri) {
39                         cur_byte = value = old[ri];
40                         count = 0;
41                 } else {
42                         if (count == 255) {
43                                 if (wi + 3 > oldsize) {
44                                         return oldsize;
45                                 }
46                                 new[wi++] = 0;
47                                 new[wi++] = count;
48                                 new[wi++] = value;
49                                 value = cur_byte = old[ri];
50                                 count = 0;
51                         } else { 
52                                 if ((cur_byte = old[ri]) == value) {
53                                         count++;
54                                 } else {
55                                         if (count > 1) {
56                                                 if (wi + 3 > oldsize) {
57                                                         return oldsize;
58                                                 }
59                                                 new[wi++] = 0;
60                                                 new[wi++] = count;
61                                                 new[wi++] = value;
62                                         } else if (count == 1) {
63                                                 if (value == 0) {
64                                                         if (wi + 3 > oldsize) {
65                                                                 return oldsize;
66                                                         }
67                                                         new[wi++] = 0;
68                                                         new[wi++] = 1;
69                                                         new[wi++] = 0;
70                                                 } else {
71                                                         if (wi + 2 > oldsize) {
72                                                                 return oldsize;
73                                                         }
74                                                         new[wi++] = value;
75                                                         new[wi++] = value;
76                                                 }
77                                         } else { /* count == 0 */
78                                                 if (value == 0) {
79                                                         if (wi + 2 > oldsize) {
80                                                                 return oldsize;
81                                                         }
82                                                         new[wi++] = value;
83                                                         new[wi++] = value;
84                                                 } else {
85                                                         if (wi + 1 > oldsize) {
86                                                                 return oldsize;
87                                                         }
88                                                         new[wi++] = value;
89                                                 }
90                                         } /* if count > 1 */
91
92                                         value = cur_byte;
93                                         count = 0;
94
95                                 } /* if byte == value */
96
97                         } /* if count == 255 */
98
99                 } /* if ri == 0 */
100                 ri++;
101
102         }
103         if (count > 1) {
104                 if (wi + 3 > oldsize) {
105                         return oldsize;
106                 }
107                 new[wi++] = 0;
108                 new[wi++] = count;
109                 new[wi++] = value;
110         } else if (count == 1) {
111                 if (value == 0) {
112                         if (wi + 3 > oldsize)
113                                 return oldsize;
114                         new[wi++] = 0;
115                         new[wi++] = 1;
116                         new[wi++] = 0;
117                 } else {
118                         if (wi + 2 > oldsize)
119                                 return oldsize;
120                         new[wi++] = value;
121                         new[wi++] = value;
122                 }
123         } else { /* count == 0 */
124                 if (value == 0) {
125                         if (wi + 2 > oldsize)
126                                 return oldsize;
127                         new[wi++] = value;
128                         new[wi++] = value;
129                 } else {
130                         if (wi + 1 > oldsize)
131                                 return oldsize;
132                         new[wi++] = value;
133                 }
134         } /* if count > 1 */
135
136         value = cur_byte;
137         count = 0;
138         return wi;
139 }
140
141 /* setup the rle compression functionality */
142 static struct __dump_compress dump_rle_compression = {
143         .compress_type = DUMP_COMPRESS_RLE,
144         .compress_func = dump_compress_rle,
145         .compress_name = "RLE",
146 };
147
148 /*
149  * Name: dump_compress_rle_init()
150  * Func: Initialize rle compression for dumping.
151  */
152 static int __init
153 dump_compress_rle_init(void)
154 {
155         dump_register_compression(&dump_rle_compression);
156         return 0;
157 }
158
159 /*
160  * Name: dump_compress_rle_cleanup()
161  * Func: Remove rle compression for dumping.
162  */
163 static void __exit
164 dump_compress_rle_cleanup(void)
165 {
166         dump_unregister_compression(DUMP_COMPRESS_RLE);
167 }
168
169 /* module initialization */
170 module_init(dump_compress_rle_init);
171 module_exit(dump_compress_rle_cleanup);
172
173 MODULE_LICENSE("GPL");
174 MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
175 MODULE_DESCRIPTION("RLE compression module for crash dump driver");