aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug13
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bug.c5
-rw-r--r--lib/check_signature.c26
-rw-r--r--lib/idr.c102
-rw-r--r--lib/percpu_counter.c68
-rw-r--r--lib/vsprintf.c173
7 files changed, 358 insertions, 31 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index fab32a286371..640844024ffd 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -152,6 +152,19 @@ config DEBUG_SLAB_LEAK
152 bool "Memory leak debugging" 152 bool "Memory leak debugging"
153 depends on DEBUG_SLAB 153 depends on DEBUG_SLAB
154 154
155config SLUB_DEBUG_ON
156 bool "SLUB debugging on by default"
157 depends on SLUB && SLUB_DEBUG
158 default n
159 help
160 Boot with debugging on by default. SLUB boots by default with
161 the runtime debug capabilities switched off. Enabling this is
162 equivalent to specifying the "slub_debug" parameter on boot.
163 There is no support for more fine grained debug control like
164 possible with slub_debug=xxx. SLUB debugging may be switched
165 off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying
166 "slub_debug=-".
167
155config DEBUG_PREEMPT 168config DEBUG_PREEMPT
156 bool "Debug preemptible kernel" 169 bool "Debug preemptible kernel"
157 depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT 170 depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
diff --git a/lib/Makefile b/lib/Makefile
index d1b366bdf86e..d7a93ff7f5a0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,7 +13,7 @@ lib-$(CONFIG_SMP) += cpumask.o
13lib-y += kobject.o kref.o kobject_uevent.o klist.o 13lib-y += kobject.o kref.o kobject_uevent.o klist.o
14 14
15obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ 15obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
16 bust_spinlocks.o hexdump.o 16 bust_spinlocks.o hexdump.o check_signature.o
17 17
18ifeq ($(CONFIG_DEBUG_KOBJECT),y) 18ifeq ($(CONFIG_DEBUG_KOBJECT),y)
19CFLAGS_kobject.o += -DDEBUG 19CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/bug.c b/lib/bug.c
index 014b582c5c4b..530f38f55787 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -38,6 +38,7 @@
38#include <linux/list.h> 38#include <linux/list.h>
39#include <linux/module.h> 39#include <linux/module.h>
40#include <linux/bug.h> 40#include <linux/bug.h>
41#include <linux/sched.h>
41 42
42extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; 43extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
43 44
@@ -112,7 +113,7 @@ const struct bug_entry *find_bug(unsigned long bugaddr)
112 return module_find_bug(bugaddr); 113 return module_find_bug(bugaddr);
113} 114}
114 115
115enum bug_trap_type report_bug(unsigned long bugaddr) 116enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
116{ 117{
117 const struct bug_entry *bug; 118 const struct bug_entry *bug;
118 const char *file; 119 const char *file;
@@ -147,7 +148,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr)
147 "[verbose debug info unavailable]\n", 148 "[verbose debug info unavailable]\n",
148 (void *)bugaddr); 149 (void *)bugaddr);
149 150
150 dump_stack(); 151 show_regs(regs);
151 return BUG_TRAP_TYPE_WARN; 152 return BUG_TRAP_TYPE_WARN;
152 } 153 }
153 154
diff --git a/lib/check_signature.c b/lib/check_signature.c
new file mode 100644
index 000000000000..fd6af199247b
--- /dev/null
+++ b/lib/check_signature.c
@@ -0,0 +1,26 @@
1#include <linux/io.h>
2#include <linux/module.h>
3
4/**
5 * check_signature - find BIOS signatures
6 * @io_addr: mmio address to check
7 * @signature: signature block
8 * @length: length of signature
9 *
10 * Perform a signature comparison with the mmio address io_addr. This
11 * address should have been obtained by ioremap.
12 * Returns 1 on a match.
13 */
14
15int check_signature(const volatile void __iomem *io_addr,
16 const unsigned char *signature, int length)
17{
18 while (length--) {
19 if (readb(io_addr) != *signature)
20 return 0;
21 io_addr++;
22 signature++;
23 }
24 return 1;
25}
26EXPORT_SYMBOL(check_signature);
diff --git a/lib/idr.c b/lib/idr.c
index b98f01a2eb94..5ca67b3cfd35 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -391,6 +391,53 @@ void idr_remove(struct idr *idp, int id)
391EXPORT_SYMBOL(idr_remove); 391EXPORT_SYMBOL(idr_remove);
392 392
393/** 393/**
394 * idr_remove_all - remove all ids from the given idr tree
395 * @idp: idr handle
396 *
397 * idr_destroy() only frees up unused, cached idp_layers, but this
398 * function will remove all id mappings and leave all idp_layers
399 * unused.
400 *
401 * A typical clean-up sequence for objects stored in an idr tree, will
402 * use idr_for_each() to free all objects, if necessay, then
403 * idr_remove_all() to remove all ids, and idr_destroy() to free
404 * up the cached idr_layers.
405 */
406void idr_remove_all(struct idr *idp)
407{
408 int n, id, max, error = 0;
409 struct idr_layer *p;
410 struct idr_layer *pa[MAX_LEVEL];
411 struct idr_layer **paa = &pa[0];
412
413 n = idp->layers * IDR_BITS;
414 p = idp->top;
415 max = 1 << n;
416
417 id = 0;
418 while (id < max && !error) {
419 while (n > IDR_BITS && p) {
420 n -= IDR_BITS;
421 *paa++ = p;
422 p = p->ary[(id >> n) & IDR_MASK];
423 }
424
425 id += 1 << n;
426 while (n < fls(id)) {
427 if (p) {
428 memset(p, 0, sizeof *p);
429 free_layer(idp, p);
430 }
431 n += IDR_BITS;
432 p = *--paa;
433 }
434 }
435 idp->top = NULL;
436 idp->layers = 0;
437}
438EXPORT_SYMBOL(idr_remove_all);
439
440/**
394 * idr_destroy - release all cached layers within an idr tree 441 * idr_destroy - release all cached layers within an idr tree
395 * idp: idr handle 442 * idp: idr handle
396 */ 443 */
@@ -437,6 +484,61 @@ void *idr_find(struct idr *idp, int id)
437EXPORT_SYMBOL(idr_find); 484EXPORT_SYMBOL(idr_find);
438 485
439/** 486/**
487 * idr_for_each - iterate through all stored pointers
488 * @idp: idr handle
489 * @fn: function to be called for each pointer
490 * @data: data passed back to callback function
491 *
492 * Iterate over the pointers registered with the given idr. The
493 * callback function will be called for each pointer currently
494 * registered, passing the id, the pointer and the data pointer passed
495 * to this function. It is not safe to modify the idr tree while in
496 * the callback, so functions such as idr_get_new and idr_remove are
497 * not allowed.
498 *
499 * We check the return of @fn each time. If it returns anything other
500 * than 0, we break out and return that value.
501 *
502 * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
503 */
504int idr_for_each(struct idr *idp,
505 int (*fn)(int id, void *p, void *data), void *data)
506{
507 int n, id, max, error = 0;
508 struct idr_layer *p;
509 struct idr_layer *pa[MAX_LEVEL];
510 struct idr_layer **paa = &pa[0];
511
512 n = idp->layers * IDR_BITS;
513 p = idp->top;
514 max = 1 << n;
515
516 id = 0;
517 while (id < max) {
518 while (n > 0 && p) {
519 n -= IDR_BITS;
520 *paa++ = p;
521 p = p->ary[(id >> n) & IDR_MASK];
522 }
523
524 if (p) {
525 error = fn(id, (void *)p, data);
526 if (error)
527 break;
528 }
529
530 id += 1 << n;
531 while (n < fls(id)) {
532 n += IDR_BITS;
533 p = *--paa;
534 }
535 }
536
537 return error;
538}
539EXPORT_SYMBOL(idr_for_each);
540
541/**
440 * idr_replace - replace pointer for given id 542 * idr_replace - replace pointer for given id
441 * @idp: idr handle 543 * @idp: idr handle
442 * @ptr: pointer you want associated with the id 544 * @ptr: pointer you want associated with the id
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 850449080e1c..cf22c617baa4 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -3,8 +3,17 @@
3 */ 3 */
4 4
5#include <linux/percpu_counter.h> 5#include <linux/percpu_counter.h>
6#include <linux/notifier.h>
7#include <linux/mutex.h>
8#include <linux/init.h>
9#include <linux/cpu.h>
6#include <linux/module.h> 10#include <linux/module.h>
7 11
12#ifdef CONFIG_HOTPLUG_CPU
13static LIST_HEAD(percpu_counters);
14static DEFINE_MUTEX(percpu_counters_lock);
15#endif
16
8void percpu_counter_mod(struct percpu_counter *fbc, s32 amount) 17void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
9{ 18{
10 long count; 19 long count;
@@ -36,7 +45,7 @@ s64 percpu_counter_sum(struct percpu_counter *fbc)
36 45
37 spin_lock(&fbc->lock); 46 spin_lock(&fbc->lock);
38 ret = fbc->count; 47 ret = fbc->count;
39 for_each_possible_cpu(cpu) { 48 for_each_online_cpu(cpu) {
40 s32 *pcount = per_cpu_ptr(fbc->counters, cpu); 49 s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
41 ret += *pcount; 50 ret += *pcount;
42 } 51 }
@@ -44,3 +53,60 @@ s64 percpu_counter_sum(struct percpu_counter *fbc)
44 return ret < 0 ? 0 : ret; 53 return ret < 0 ? 0 : ret;
45} 54}
46EXPORT_SYMBOL(percpu_counter_sum); 55EXPORT_SYMBOL(percpu_counter_sum);
56
57void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
58{
59 spin_lock_init(&fbc->lock);
60 fbc->count = amount;
61 fbc->counters = alloc_percpu(s32);
62#ifdef CONFIG_HOTPLUG_CPU
63 mutex_lock(&percpu_counters_lock);
64 list_add(&fbc->list, &percpu_counters);
65 mutex_unlock(&percpu_counters_lock);
66#endif
67}
68EXPORT_SYMBOL(percpu_counter_init);
69
70void percpu_counter_destroy(struct percpu_counter *fbc)
71{
72 free_percpu(fbc->counters);
73#ifdef CONFIG_HOTPLUG_CPU
74 mutex_lock(&percpu_counters_lock);
75 list_del(&fbc->list);
76 mutex_unlock(&percpu_counters_lock);
77#endif
78}
79EXPORT_SYMBOL(percpu_counter_destroy);
80
81#ifdef CONFIG_HOTPLUG_CPU
82static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb,
83 unsigned long action, void *hcpu)
84{
85 unsigned int cpu;
86 struct percpu_counter *fbc;
87
88 if (action != CPU_DEAD)
89 return NOTIFY_OK;
90
91 cpu = (unsigned long)hcpu;
92 mutex_lock(&percpu_counters_lock);
93 list_for_each_entry(fbc, &percpu_counters, list) {
94 s32 *pcount;
95
96 spin_lock(&fbc->lock);
97 pcount = per_cpu_ptr(fbc->counters, cpu);
98 fbc->count += *pcount;
99 *pcount = 0;
100 spin_unlock(&fbc->lock);
101 }
102 mutex_unlock(&percpu_counters_lock);
103 return NOTIFY_OK;
104}
105
106static int __init percpu_counter_startup(void)
107{
108 hotcpu_notifier(percpu_counter_hotcpu_callback, 0);
109 return 0;
110}
111module_init(percpu_counter_startup);
112#endif
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 017290241261..6b6734df6d2d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -135,6 +135,103 @@ static int skip_atoi(const char **s)
135 return i; 135 return i;
136} 136}
137 137
138/* Decimal conversion is by far the most typical, and is used
139 * for /proc and /sys data. This directly impacts e.g. top performance
140 * with many processes running. We optimize it for speed
141 * using code from
142 * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
143 * (with permission from the author, Douglas W. Jones). */
144
145/* Formats correctly any integer in [0,99999].
146 * Outputs from one to five digits depending on input.
147 * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
148static char* put_dec_trunc(char *buf, unsigned q)
149{
150 unsigned d3, d2, d1, d0;
151 d1 = (q>>4) & 0xf;
152 d2 = (q>>8) & 0xf;
153 d3 = (q>>12);
154
155 d0 = 6*(d3 + d2 + d1) + (q & 0xf);
156 q = (d0 * 0xcd) >> 11;
157 d0 = d0 - 10*q;
158 *buf++ = d0 + '0'; /* least significant digit */
159 d1 = q + 9*d3 + 5*d2 + d1;
160 if (d1 != 0) {
161 q = (d1 * 0xcd) >> 11;
162 d1 = d1 - 10*q;
163 *buf++ = d1 + '0'; /* next digit */
164
165 d2 = q + 2*d2;
166 if ((d2 != 0) || (d3 != 0)) {
167 q = (d2 * 0xd) >> 7;
168 d2 = d2 - 10*q;
169 *buf++ = d2 + '0'; /* next digit */
170
171 d3 = q + 4*d3;
172 if (d3 != 0) {
173 q = (d3 * 0xcd) >> 11;
174 d3 = d3 - 10*q;
175 *buf++ = d3 + '0'; /* next digit */
176 if (q != 0)
177 *buf++ = q + '0'; /* most sign. digit */
178 }
179 }
180 }
181 return buf;
182}
183/* Same with if's removed. Always emits five digits */
184static char* put_dec_full(char *buf, unsigned q)
185{
186 /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
187 /* but anyway, gcc produces better code with full-sized ints */
188 unsigned d3, d2, d1, d0;
189 d1 = (q>>4) & 0xf;
190 d2 = (q>>8) & 0xf;
191 d3 = (q>>12);
192
193 /* Possible ways to approx. divide by 10 */
194 /* gcc -O2 replaces multiply with shifts and adds */
195 // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
196 // (x * 0x67) >> 10: 1100111
197 // (x * 0x34) >> 9: 110100 - same
198 // (x * 0x1a) >> 8: 11010 - same
199 // (x * 0x0d) >> 7: 1101 - same, shortest code (on i386)
200
201 d0 = 6*(d3 + d2 + d1) + (q & 0xf);
202 q = (d0 * 0xcd) >> 11;
203 d0 = d0 - 10*q;
204 *buf++ = d0 + '0';
205 d1 = q + 9*d3 + 5*d2 + d1;
206 q = (d1 * 0xcd) >> 11;
207 d1 = d1 - 10*q;
208 *buf++ = d1 + '0';
209
210 d2 = q + 2*d2;
211 q = (d2 * 0xd) >> 7;
212 d2 = d2 - 10*q;
213 *buf++ = d2 + '0';
214
215 d3 = q + 4*d3;
216 q = (d3 * 0xcd) >> 11; /* - shorter code */
217 /* q = (d3 * 0x67) >> 10; - would also work */
218 d3 = d3 - 10*q;
219 *buf++ = d3 + '0';
220 *buf++ = q + '0';
221 return buf;
222}
223/* No inlining helps gcc to use registers better */
224static noinline char* put_dec(char *buf, unsigned long long num)
225{
226 while (1) {
227 unsigned rem;
228 if (num < 100000)
229 return put_dec_trunc(buf, num);
230 rem = do_div(num, 100000);
231 buf = put_dec_full(buf, rem);
232 }
233}
234
138#define ZEROPAD 1 /* pad with zero */ 235#define ZEROPAD 1 /* pad with zero */
139#define SIGN 2 /* unsigned/signed long */ 236#define SIGN 2 /* unsigned/signed long */
140#define PLUS 4 /* show plus */ 237#define PLUS 4 /* show plus */
@@ -143,12 +240,14 @@ static int skip_atoi(const char **s)
143#define SPECIAL 32 /* 0x */ 240#define SPECIAL 32 /* 0x */
144#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 241#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
145 242
146static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) 243static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
147{ 244{
148 char c,sign,tmp[66]; 245 char sign,tmp[66];
149 const char *digits; 246 const char *digits;
150 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 247 /* we are called with base 8, 10 or 16, only, thus don't need "g..." */
151 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 248 static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
249 static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
250 int need_pfx = ((type & SPECIAL) && base != 10);
152 int i; 251 int i;
153 252
154 digits = (type & LARGE) ? large_digits : small_digits; 253 digits = (type & LARGE) ? large_digits : small_digits;
@@ -156,7 +255,6 @@ static char * number(char * buf, char * end, unsigned long long num, int base, i
156 type &= ~ZEROPAD; 255 type &= ~ZEROPAD;
157 if (base < 2 || base > 36) 256 if (base < 2 || base > 36)
158 return NULL; 257 return NULL;
159 c = (type & ZEROPAD) ? '0' : ' ';
160 sign = 0; 258 sign = 0;
161 if (type & SIGN) { 259 if (type & SIGN) {
162 if ((signed long long) num < 0) { 260 if ((signed long long) num < 0) {
@@ -171,64 +269,85 @@ static char * number(char * buf, char * end, unsigned long long num, int base, i
171 size--; 269 size--;
172 } 270 }
173 } 271 }
174 if (type & SPECIAL) { 272 if (need_pfx) {
273 size--;
175 if (base == 16) 274 if (base == 16)
176 size -= 2;
177 else if (base == 8)
178 size--; 275 size--;
179 } 276 }
277
278 /* generate full string in tmp[], in reverse order */
180 i = 0; 279 i = 0;
181 if (num == 0) 280 if (num == 0)
182 tmp[i++]='0'; 281 tmp[i++] = '0';
183 else while (num != 0) 282 /* Generic code, for any base:
283 else do {
184 tmp[i++] = digits[do_div(num,base)]; 284 tmp[i++] = digits[do_div(num,base)];
285 } while (num != 0);
286 */
287 else if (base != 10) { /* 8 or 16 */
288 int mask = base - 1;
289 int shift = 3;
290 if (base == 16) shift = 4;
291 do {
292 tmp[i++] = digits[((unsigned char)num) & mask];
293 num >>= shift;
294 } while (num);
295 } else { /* base 10 */
296 i = put_dec(tmp, num) - tmp;
297 }
298
299 /* printing 100 using %2d gives "100", not "00" */
185 if (i > precision) 300 if (i > precision)
186 precision = i; 301 precision = i;
302 /* leading space padding */
187 size -= precision; 303 size -= precision;
188 if (!(type&(ZEROPAD+LEFT))) { 304 if (!(type & (ZEROPAD+LEFT))) {
189 while(size-->0) { 305 while(--size >= 0) {
190 if (buf < end) 306 if (buf < end)
191 *buf = ' '; 307 *buf = ' ';
192 ++buf; 308 ++buf;
193 } 309 }
194 } 310 }
311 /* sign */
195 if (sign) { 312 if (sign) {
196 if (buf < end) 313 if (buf < end)
197 *buf = sign; 314 *buf = sign;
198 ++buf; 315 ++buf;
199 } 316 }
200 if (type & SPECIAL) { 317 /* "0x" / "0" prefix */
201 if (base==8) { 318 if (need_pfx) {
202 if (buf < end) 319 if (buf < end)
203 *buf = '0'; 320 *buf = '0';
204 ++buf; 321 ++buf;
205 } else if (base==16) { 322 if (base == 16) {
206 if (buf < end)
207 *buf = '0';
208 ++buf;
209 if (buf < end) 323 if (buf < end)
210 *buf = digits[33]; 324 *buf = digits[16]; /* for arbitrary base: digits[33]; */
211 ++buf; 325 ++buf;
212 } 326 }
213 } 327 }
328 /* zero or space padding */
214 if (!(type & LEFT)) { 329 if (!(type & LEFT)) {
215 while (size-- > 0) { 330 char c = (type & ZEROPAD) ? '0' : ' ';
331 while (--size >= 0) {
216 if (buf < end) 332 if (buf < end)
217 *buf = c; 333 *buf = c;
218 ++buf; 334 ++buf;
219 } 335 }
220 } 336 }
221 while (i < precision--) { 337 /* hmm even more zero padding? */
338 while (i <= --precision) {
222 if (buf < end) 339 if (buf < end)
223 *buf = '0'; 340 *buf = '0';
224 ++buf; 341 ++buf;
225 } 342 }
226 while (i-- > 0) { 343 /* actual digits of result */
344 while (--i >= 0) {
227 if (buf < end) 345 if (buf < end)
228 *buf = tmp[i]; 346 *buf = tmp[i];
229 ++buf; 347 ++buf;
230 } 348 }
231 while (size-- > 0) { 349 /* trailing space padding */
350 while (--size >= 0) {
232 if (buf < end) 351 if (buf < end)
233 *buf = ' '; 352 *buf = ' ';
234 ++buf; 353 ++buf;
@@ -276,7 +395,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
276 used for unknown buffer sizes. */ 395 used for unknown buffer sizes. */
277 if (unlikely((int) size < 0)) { 396 if (unlikely((int) size < 0)) {
278 /* There can be only one.. */ 397 /* There can be only one.. */
279 static int warn = 1; 398 static char warn = 1;
280 WARN_ON(warn); 399 WARN_ON(warn);
281 warn = 0; 400 warn = 0;
282 return 0; 401 return 0;