[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Add cpumask_scnprintf() and cpulist_scnprintf(). This also
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID b866ed85fad37ebcf198f9ca8aff7dac916d174d # Parent 4c2c02ca4a7aa6161c98077ea4fd6d24f5dac58d Add cpumask_scnprintf() and cpulist_scnprintf(). This also adds the bitmap_scnprintf functions and scnprintf itself. Add dirty cpu and cpu affinity info to 'q'-key debug output. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/common/bitmap.c --- a/xen/common/bitmap.c Sat Jan 7 17:16:10 2006 +++ b/xen/common/bitmap.c Sat Jan 7 17:17:13 2006 @@ -282,6 +282,111 @@ #endif EXPORT_SYMBOL(__bitmap_weight); +/* + * Bitmap printing & parsing functions: first version by Bill Irwin, + * second version by Paul Jackson, third by Joe Korty. + */ + +#define CHUNKSZ 32 +#define nbits_to_hold_value(val) fls(val) +#define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1)) +#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10)) +#define BASEDEC 10 /* fancier cpuset lists input in decimal */ + +/** + * bitmap_scnprintf - convert bitmap to an ASCII hex string. + * @buf: byte buffer into which string is placed + * @buflen: reserved size of @buf, in bytes + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * + * Exactly @nmaskbits bits are displayed. Hex digits are grouped into + * comma-separated sets of eight digits per set. + */ +int bitmap_scnprintf(char *buf, unsigned int buflen, + const unsigned long *maskp, int nmaskbits) +{ + int i, word, bit, len = 0; + unsigned long val; + const char *sep = ""; + int chunksz; + u32 chunkmask; + + chunksz = nmaskbits & (CHUNKSZ - 1); + if (chunksz == 0) + chunksz = CHUNKSZ; + + i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ; + for (; i >= 0; i -= CHUNKSZ) { + chunkmask = ((1ULL << chunksz) - 1); + word = i / BITS_PER_LONG; + bit = i % BITS_PER_LONG; + val = (maskp[word] >> bit) & chunkmask; + len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep, + (chunksz+3)/4, val); + chunksz = CHUNKSZ; + sep = ","; + } + return len; +} +EXPORT_SYMBOL(bitmap_scnprintf); + +/* + * bscnl_emit(buf, buflen, rbot, rtop, bp) + * + * Helper routine for bitmap_scnlistprintf(). Write decimal number + * or range to buf, suppressing output past buf+buflen, with optional + * comma-prefix. Return len of what would be written to buf, if it + * all fit. + */ +static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len) +{ + if (len > 0) + len += scnprintf(buf + len, buflen - len, ","); + if (rbot == rtop) + len += scnprintf(buf + len, buflen - len, "%d", rbot); + else + len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop); + return len; +} + +/** + * bitmap_scnlistprintf - convert bitmap to list format ASCII string + * @buf: byte buffer into which string is placed + * @buflen: reserved size of @buf, in bytes + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * + * Output format is a comma-separated list of decimal numbers and + * ranges. Consecutively set bits are shown as two hyphen-separated + * decimal numbers, the smallest and largest bit numbers set in + * the range. Output format is compatible with the format + * accepted as input by bitmap_parselist(). + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing '\0', as + * per ISO C99. + */ +int bitmap_scnlistprintf(char *buf, unsigned int buflen, + const unsigned long *maskp, int nmaskbits) +{ + int len = 0; + /* current bit is 'cur', most recently seen range is [rbot, rtop] */ + int cur, rbot, rtop; + + rbot = cur = find_first_bit(maskp, nmaskbits); + while (cur < nmaskbits) { + rtop = cur; + cur = find_next_bit(maskp, nmaskbits, cur+1); + if (cur >= nmaskbits || cur > rtop + 1) { + len = bscnl_emit(buf, buflen, rbot, rtop, len); + rbot = cur; + } + } + return len; +} +EXPORT_SYMBOL(bitmap_scnlistprintf); + /** * bitmap_find_free_region - find a contiguous aligned mem region * @bitmap: an array of unsigned longs corresponding to the bitmap diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/common/keyhandler.c --- a/xen/common/keyhandler.c Sat Jan 7 17:16:10 2006 +++ b/xen/common/keyhandler.c Sat Jan 7 17:17:13 2006 @@ -97,13 +97,22 @@ machine_restart(NULL); } -static void do_task_queues(unsigned char key) +static void cpuset_print(char *set, int size, cpumask_t mask) +{ + *set++ = '{'; + set += cpulist_scnprintf(set, size-2, mask); + *set++ = '}'; + *set++ = '\0'; +} + +static void dump_domains(unsigned char key) { struct domain *d; struct vcpu *v; s_time_t now = NOW(); - - printk("'%c' pressed -> dumping task queues (now=0x%X:%08X)\n", key, + char cpuset[100]; + + printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key, (u32)(now>>32), (u32)now); read_lock(&domlist_lock); @@ -111,9 +120,11 @@ for_each_domain ( d ) { printk("General information for domain %u:\n", d->domain_id); - printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d\n", + cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask); + printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d " + "dirty_cpus=%s\n", d->domain_flags, atomic_read(&d->refcnt), - d->tot_pages, d->xenheap_pages); + d->tot_pages, d->xenheap_pages, cpuset); printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x\n", d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3], @@ -129,12 +140,16 @@ d->domain_id); for_each_vcpu ( d, v ) { printk(" VCPU%d: CPU%d [has=%c] flags=%lx " - "upcall_pend = %02x, upcall_mask = %02x\n", + "upcall_pend = %02x, upcall_mask = %02x ", v->vcpu_id, v->processor, test_bit(_VCPUF_running, &v->vcpu_flags) ? 'T':'F', v->vcpu_flags, v->vcpu_info->evtchn_upcall_pending, v->vcpu_info->evtchn_upcall_mask); + cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask); + printk("dirty_cpus=%s ", cpuset); + cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity); + printk("cpu_affinity=%s\n", cpuset); printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n", VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG], test_bit(v->virq_to_evtchn[VIRQ_DEBUG], @@ -193,7 +208,7 @@ register_keyhandler( 'L', reset_sched_histo, "reset sched latency histogram"); register_keyhandler( - 'q', do_task_queues, "dump task queues + guest state"); + 'q', dump_domains, "dump domain (and guest debug) info"); register_keyhandler( 'r', dump_runq, "dump run queues"); register_irq_keyhandler( diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/common/vsprintf.c --- a/xen/common/vsprintf.c Sat Jan 7 17:16:10 2006 +++ b/xen/common/vsprintf.c Sat Jan 7 17:17:13 2006 @@ -12,11 +12,15 @@ /* * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@xxxxxxxxxxxxxx> * - changed to provide snprintf and vsnprintf functions + * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@xxxxxxx> + * - scnprintf and vscnprintf */ #include <stdarg.h> #include <xen/ctype.h> #include <xen/lib.h> +#include <asm/div64.h> +#include <asm/page.h> /** * simple_strtoul - convert a string to an unsigned long @@ -33,11 +37,14 @@ if (*cp == '0') { base = 8; cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { + if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { cp++; base = 16; } } + } else if (base == 16) { + if (cp[0] == '0' && toupper(cp[1]) == 'X') + cp += 2; } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { @@ -49,6 +56,8 @@ return result; } +EXPORT_SYMBOL(simple_strtoul); + /** * simple_strtol - convert a string to a signed long * @cp: The start of the string @@ -61,6 +70,8 @@ return -simple_strtoul(cp+1,endp,base); return simple_strtoul(cp,endp,base); } + +EXPORT_SYMBOL(simple_strtol); /** * simple_strtoull - convert a string to an unsigned long long @@ -77,11 +88,14 @@ if (*cp == '0') { base = 8; cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { + if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { cp++; base = 16; } } + } else if (base == 16) { + if (cp[0] == '0' && toupper(cp[1]) == 'X') + cp += 2; } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base) { @@ -92,6 +106,8 @@ *endp = (char *)cp; return result; } + +EXPORT_SYMBOL(simple_strtoull); /** * simple_strtoll - convert a string to a signed long long @@ -123,25 +139,25 @@ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) +static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; - const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; digits = (type & LARGE) ? large_digits : small_digits; if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) - return buf; + return NULL; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { - if (num < 0) { + if ((signed long long) num < 0) { sign = '-'; - num = -num; + num = - (signed long long) num; size--; } else if (type & PLUS) { sign = '+'; @@ -160,6 +176,9 @@ i = 0; if (num == 0) tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; +#if 0 else { /* XXX KAF: force unsigned mod and div. */ @@ -167,6 +186,7 @@ unsigned int base2=(unsigned int)base; while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; } } +#endif if (i > precision) precision = i; size -= precision; @@ -222,14 +242,22 @@ } /** -* vsnprintf - Format a string and place it in a buffer -* @buf: The buffer to place the result into -* @size: The size of the buffer, including the trailing null space -* @fmt: The format string to use -* @args: Arguments for the format string -* -* Call this function if you are already dealing with a va_list. -* You probably want snprintf instead. + * vsnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the number of characters which would + * be generated for the given input, excluding the trailing + * '\0', as per ISO C99. If you want to have the exact + * number of characters written into @buf as return value + * (not including the trailing '\0'), use vscnprintf. If the + * return is greater than or equal to @size, the resulting + * string is truncated. + * + * Call this function if you are already dealing with a va_list. + * You probably want snprintf instead. */ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { @@ -247,6 +275,9 @@ int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ /* 'z' changed to 'Z' --davidm 1/25/99 */ + + /* Reject out-of-range values early */ + BUG_ON((int)size < 0); str = buf; end = buf + size - 1; @@ -307,17 +338,14 @@ /* get the conversion qualifier */ qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || + *fmt =='Z' || *fmt == 'z') { qualifier = *fmt; ++fmt; if (qualifier == 'l' && *fmt == 'l') { qualifier = 'L'; ++fmt; } - } - if (*fmt == 'q') { - qualifier = 'L'; - ++fmt; } /* default base */ @@ -345,7 +373,7 @@ case 's': s = va_arg(args, char *); - if (!s) + if ((unsigned long)s < PAGE_SIZE) s = "<NULL>"; len = strnlen(s, precision); @@ -386,7 +414,7 @@ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); - } else if (qualifier == 'Z') { + } else if (qualifier == 'Z' || qualifier == 'z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { @@ -437,7 +465,7 @@ num = va_arg(args, unsigned long); if (flags & SIGN) num = (signed long) num; - } else if (qualifier == 'Z') { + } else if (qualifier == 'Z' || qualifier == 'z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); @@ -463,12 +491,43 @@ return str-buf; } +EXPORT_SYMBOL(vsnprintf); + +/** + * vscnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the number of characters which have been written into + * the @buf not including the trailing '\0'. If @size is <= 0 the function + * returns 0. + * + * Call this function if you are already dealing with a va_list. + * You probably want scnprintf instead. + */ +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int i; + + i=vsnprintf(buf,size,fmt,args); + return (i >= size) ? (size - 1) : i; +} + +EXPORT_SYMBOL(vscnprintf); + /** * snprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space * @fmt: The format string to use * @...: Arguments for the format string + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing null, + * as per ISO C99. If the return is greater than or equal to + * @size, the resulting string is truncated. */ int snprintf(char * buf, size_t size, const char *fmt, ...) { @@ -481,26 +540,61 @@ return i; } +EXPORT_SYMBOL(snprintf); + +/** + * scnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters written into @buf not including + * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is + * greater than or equal to @size, the resulting string is truncated. + */ + +int scnprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, size, fmt, args); + va_end(args); + return (i >= size) ? (size - 1) : i; +} +EXPORT_SYMBOL(scnprintf); + /** * vsprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @fmt: The format string to use * @args: Arguments for the format string * + * The function returns the number of characters written + * into @buf. Use vsnprintf or vscnprintf in order to avoid + * buffer overflows. + * * Call this function if you are already dealing with a va_list. * You probably want sprintf instead. */ int vsprintf(char *buf, const char *fmt, va_list args) { - return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args); -} - + return vsnprintf(buf, INT_MAX, fmt, args); +} + +EXPORT_SYMBOL(vsprintf); /** * sprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @fmt: The format string to use * @...: Arguments for the format string + * + * The function returns the number of characters written + * into @buf. Use snprintf or scnprintf in order to avoid + * buffer overflows. */ int sprintf(char * buf, const char *fmt, ...) { @@ -508,11 +602,12 @@ int i; va_start(args, fmt); - i=vsprintf(buf,fmt,args); + i=vsnprintf(buf, INT_MAX, fmt, args); va_end(args); return i; } +EXPORT_SYMBOL(sprintf); /* * Local variables: diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/include/xen/bitmap.h --- a/xen/include/xen/bitmap.h Sat Jan 7 17:16:10 2006 +++ b/xen/include/xen/bitmap.h Sat Jan 7 17:17:13 2006 @@ -41,6 +41,8 @@ * bitmap_weight(src, nbits) Hamming Weight: number set bits * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n + * bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf + * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf */ /* @@ -93,6 +95,10 @@ const unsigned long *bitmap2, int bits); extern int __bitmap_weight(const unsigned long *bitmap, int bits); +extern int bitmap_scnprintf(char *buf, unsigned int len, + const unsigned long *src, int nbits); +extern int bitmap_scnlistprintf(char *buf, unsigned int len, + const unsigned long *src, int nbits); extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order); extern void bitmap_release_region(unsigned long *bitmap, int pos, int order); extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order); diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/include/xen/cpumask.h --- a/xen/include/xen/cpumask.h Sat Jan 7 17:16:10 2006 +++ b/xen/include/xen/cpumask.h Sat Jan 7 17:17:13 2006 @@ -8,8 +8,8 @@ * See detailed comments in the file xen/bitmap.h describing the * data type on which these cpumasks are based. * - * For details of cpumask_scnprintf() and cpumask_parse(), - * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. + * For details of cpumask_scnprintf() and cpulist_scnprintf(), + * see bitmap_scnprintf() and bitmap_scnlistprintf() in lib/bitmap.c. * * The available cpumask operations are: * @@ -36,8 +36,8 @@ * void cpus_shift_right(dst, src, n) Shift right * void cpus_shift_left(dst, src, n) Shift left * - * int first_cpu(mask) Number lowest set bit, or >= NR_CPUS - * int next_cpu(cpu, mask) Next cpu past 'cpu', or >= NR_CPUS + * int first_cpu(mask) Number lowest set bit, or NR_CPUS + * int next_cpu(cpu, mask) Next cpu past 'cpu', or NR_CPUS * * cpumask_t cpumask_of_cpu(cpu) Return cpumask with bit 'cpu' set * CPU_MASK_ALL Initializer - all bits set @@ -45,7 +45,7 @@ * unsigned long *cpus_addr(mask) Array of unsigned long's in mask * * int cpumask_scnprintf(buf, len, mask) Format cpumask for printing - * int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask + * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing * * for_each_cpu_mask(cpu, mask) for-loop cpu over mask * @@ -207,13 +207,13 @@ #define first_cpu(src) __first_cpu(&(src), NR_CPUS) static inline int __first_cpu(const cpumask_t *srcp, int nbits) { - return find_first_bit(srcp->bits, nbits); + return min_t(int, nbits, find_first_bit(srcp->bits, nbits)); } #define next_cpu(n, src) __next_cpu((n), &(src), NR_CPUS) static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits) { - return find_next_bit(srcp->bits, nbits, n+1); + return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1)); } #define cpumask_of_cpu(cpu) \ @@ -259,7 +259,6 @@ #define cpus_addr(src) ((src).bits) -/* #define cpumask_scnprintf(buf, len, src) \ __cpumask_scnprintf((buf), (len), &(src), NR_CPUS) static inline int __cpumask_scnprintf(char *buf, int len, @@ -268,14 +267,13 @@ return bitmap_scnprintf(buf, len, srcp->bits, nbits); } -#define cpumask_parse(ubuf, ulen, src) \ - __cpumask_parse((ubuf), (ulen), &(src), NR_CPUS) -static inline int __cpumask_parse(const char __user *buf, int len, - cpumask_t *dstp, int nbits) -{ - return bitmap_parse(buf, len, dstp->bits, nbits); -} -*/ +#define cpulist_scnprintf(buf, len, src) \ + __cpulist_scnprintf((buf), (len), &(src), NR_CPUS) +static inline int __cpulist_scnprintf(char *buf, int len, + const cpumask_t *srcp, int nbits) +{ + return bitmap_scnlistprintf(buf, len, srcp->bits, nbits); +} #if NR_CPUS > 1 #define for_each_cpu_mask(cpu, mask) \ @@ -368,7 +366,7 @@ for_each_cpu_mask(cpu, (mask)) \ if (cpu_online(cpu)) \ break; \ - min_t(int, NR_CPUS, cpu); \ + cpu; \ }) #define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) diff -r 4c2c02ca4a7a -r b866ed85fad3 xen/include/xen/lib.h --- a/xen/include/xen/lib.h Sat Jan 7 17:16:10 2006 +++ b/xen/include/xen/lib.h Sat Jan 7 17:17:13 2006 @@ -53,10 +53,16 @@ /* vsprintf.c */ extern int sprintf(char * buf, const char * fmt, ...) __attribute__ ((format (printf, 2, 3))); -extern int vsprintf(char *buf, const char *, va_list); +extern int vsprintf(char *buf, const char *, va_list) + __attribute__ ((format (printf, 2, 0))); extern int snprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); +extern int scnprintf(char * buf, size_t size, const char * fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); long simple_strtol( const char *cp,char **endp, unsigned int base); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |