vtxprintf: Introduce vtxdprintf for the ease of closures

It was suggested to eliminate the lock for sprintf. One way to do it is
to make the fake tx_byte into a closure. This patch allows it.

It's a bit tricky since we need to preserve compatibility with romcc.

Change-Id: I877ef0cef54dcbb0589fe858c485f76f3dd27ece
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-on: http://review.coreboot.org/4287
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Vladimir Serbinenko 2013-11-26 21:43:05 +01:00
parent 7f68dfd6e8
commit f421b33edb
2 changed files with 56 additions and 23 deletions

View File

@ -8,6 +8,16 @@
#include <console/console.h> #include <console/console.h>
#include <console/vtxprintf.h> #include <console/vtxprintf.h>
#if !defined (__ROMCC__) && !defined(__SMM__)
#define DATA_ARG , data
#define DATA_ARG_DECL , void *data
#else
#define DATA_ARG
#define DATA_ARG_DECL
#endif
#define call_tx(x) tx_byte(x DATA_ARG)
/* haha, don't need ctype.c */ /* haha, don't need ctype.c */
#define isdigit(c) ((c) >= '0' && (c) <= '9') #define isdigit(c) ((c) >= '0' && (c) <= '9')
#define is_digit isdigit #define is_digit isdigit
@ -30,8 +40,9 @@ static int skip_atoi(const char **s)
#define SPECIAL 32 /* 0x */ #define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
static int number(void (*tx_byte)(unsigned char byte), static int number(void (*tx_byte)(unsigned char byte DATA_ARG_DECL),
unsigned long long num, int base, int size, int precision, int type) unsigned long long num, int base, int size, int precision, int type
DATA_ARG_DECL)
{ {
char c,sign,tmp[66]; char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
@ -77,31 +88,36 @@ static int number(void (*tx_byte)(unsigned char byte),
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
tx_byte(' '), count++; call_tx(' '), count++;
if (sign) if (sign)
tx_byte(sign), count++; call_tx(sign), count++;
if (type & SPECIAL) { if (type & SPECIAL) {
if (base==8) if (base==8)
tx_byte('0'), count++; call_tx('0'), count++;
else if (base==16) { else if (base==16) {
tx_byte('0'), count++; call_tx('0'), count++;
tx_byte(digits[33]), count++; call_tx(digits[33]), count++;
} }
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
tx_byte(c), count++; call_tx(c), count++;
while (i < precision--) while (i < precision--)
tx_byte('0'), count++; call_tx('0'), count++;
while (i-- > 0) while (i-- > 0)
tx_byte(tmp[i]), count++; call_tx(tmp[i]), count++;
while (size-- > 0) while (size-- > 0)
tx_byte(' '), count++; call_tx(' '), count++;
return count; return count;
} }
#if !defined (__ROMCC__) && !defined(__SMM__)
int vtxdprintf(void (*tx_byte)(unsigned char byte, void *data),
const char *fmt, va_list args, void *data)
#else
int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args) int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args)
#endif
{ {
int len; int len;
unsigned long long num; unsigned long long num;
@ -124,7 +140,7 @@ int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args
for (count=0; *fmt ; ++fmt) { for (count=0; *fmt ; ++fmt) {
if (*fmt != '%') { if (*fmt != '%') {
tx_byte(*fmt), count++; call_tx(*fmt), count++;
continue; continue;
} }
@ -187,10 +203,10 @@ repeat:
case 'c': case 'c':
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
tx_byte(' '), count++; call_tx(' '), count++;
tx_byte((unsigned char) va_arg(args, int)), count++; call_tx((unsigned char) va_arg(args, int)), count++;
while (--field_width > 0) while (--field_width > 0)
tx_byte(' '), count++; call_tx(' '), count++;
continue; continue;
case 's': case 's':
@ -202,11 +218,11 @@ repeat:
if (!(flags & LEFT)) if (!(flags & LEFT))
while (len < field_width--) while (len < field_width--)
tx_byte(' '), count++; call_tx(' '), count++;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
tx_byte(*s++), count++; call_tx(*s++), count++;
while (len < field_width--) while (len < field_width--)
tx_byte(' '), count++; call_tx(' '), count++;
continue; continue;
case 'p': case 'p':
@ -216,7 +232,7 @@ repeat:
} }
count += number(tx_byte, count += number(tx_byte,
(unsigned long) va_arg(args, void *), 16, (unsigned long) va_arg(args, void *), 16,
field_width, precision, flags); field_width, precision, flags DATA_ARG);
continue; continue;
case 'n': case 'n':
@ -233,7 +249,7 @@ repeat:
continue; continue;
case '%': case '%':
tx_byte('%'), count++; call_tx('%'), count++;
continue; continue;
/* integer number formats - set up the flags and "break" */ /* integer number formats - set up the flags and "break" */
@ -254,9 +270,9 @@ repeat:
break; break;
default: default:
tx_byte('%'), count++; call_tx('%'), count++;
if (*fmt) if (*fmt)
tx_byte(*fmt), count++; call_tx(*fmt), count++;
else else
--fmt; --fmt;
continue; continue;
@ -276,8 +292,21 @@ repeat:
} else { } else {
num = va_arg(args, unsigned int); num = va_arg(args, unsigned int);
} }
count += number(tx_byte, num, base, field_width, precision, flags); count += number(tx_byte, num, base, field_width, precision, flags DATA_ARG);
} }
return count; return count;
} }
#if !defined (__ROMCC__) && !defined(__SMM__)
static void wrap_tx_byte (unsigned char byte, void *data)
{
void (*tx_byte)(unsigned char byte) = data;
tx_byte (byte);
}
int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args)
{
return vtxdprintf(wrap_tx_byte, fmt, args, tx_byte);
}
#endif

View File

@ -36,4 +36,8 @@ typedef __builtin_va_list va_list;
int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args); int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args);
#if !defined (__ROMCC__) && !defined (__SMM__)
int vtxdprintf(void (*tx_byte)(unsigned char byte, void *data), const char *fmt, va_list args, void *data);
#endif
#endif #endif