diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig.debug | 13 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/bug.c | 5 | ||||
| -rw-r--r-- | lib/check_signature.c | 26 | ||||
| -rw-r--r-- | lib/idr.c | 102 | ||||
| -rw-r--r-- | lib/percpu_counter.c | 68 | ||||
| -rw-r--r-- | lib/vsprintf.c | 173 |
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 | ||
| 155 | config 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 | |||
| 155 | config DEBUG_PREEMPT | 168 | config 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 | |||
| 13 | lib-y += kobject.o kref.o kobject_uevent.o klist.o | 13 | lib-y += kobject.o kref.o kobject_uevent.o klist.o |
| 14 | 14 | ||
| 15 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 15 | obj-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 | ||
| 18 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) | 18 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) |
| 19 | CFLAGS_kobject.o += -DDEBUG | 19 | CFLAGS_kobject.o += -DDEBUG |
| @@ -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 | ||
| 42 | extern const struct bug_entry __start___bug_table[], __stop___bug_table[]; | 43 | extern 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 | ||
| 115 | enum bug_trap_type report_bug(unsigned long bugaddr) | 116 | enum 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 | |||
| 15 | int 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 | } | ||
| 26 | EXPORT_SYMBOL(check_signature); | ||
| @@ -391,6 +391,53 @@ void idr_remove(struct idr *idp, int id) | |||
| 391 | EXPORT_SYMBOL(idr_remove); | 391 | EXPORT_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 | */ | ||
| 406 | void 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 | } | ||
| 438 | EXPORT_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) | |||
| 437 | EXPORT_SYMBOL(idr_find); | 484 | EXPORT_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 | */ | ||
| 504 | int 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 | } | ||
| 539 | EXPORT_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 | ||
| 13 | static LIST_HEAD(percpu_counters); | ||
| 14 | static DEFINE_MUTEX(percpu_counters_lock); | ||
| 15 | #endif | ||
| 16 | |||
| 8 | void percpu_counter_mod(struct percpu_counter *fbc, s32 amount) | 17 | void 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 | } |
| 46 | EXPORT_SYMBOL(percpu_counter_sum); | 55 | EXPORT_SYMBOL(percpu_counter_sum); |
| 56 | |||
| 57 | void 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 | } | ||
| 68 | EXPORT_SYMBOL(percpu_counter_init); | ||
| 69 | |||
| 70 | void 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 | } | ||
| 79 | EXPORT_SYMBOL(percpu_counter_destroy); | ||
| 80 | |||
| 81 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 82 | static 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 | |||
| 106 | static int __init percpu_counter_startup(void) | ||
| 107 | { | ||
| 108 | hotcpu_notifier(percpu_counter_hotcpu_callback, 0); | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | module_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. */ | ||
| 148 | static 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 */ | ||
| 184 | static 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 */ | ||
| 224 | static 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 | ||
| 146 | static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) | 243 | static 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; |
