improve strerror speed

change the current O(n) lookup to O(1) based on the machinery
described in "How To Write Shared Libraries" (Appendix B).
This commit is contained in:
Timo Teräs 2020-03-04 11:27:01 +02:00 committed by Rich Felker
parent 2b2c8aafce
commit 8343334d7b
2 changed files with 32 additions and 22 deletions

View file

@ -1,8 +1,9 @@
/* This file is sorted such that 'errors' which represent exceptional /* The first entry is a catch-all for codes not enumerated here.
* conditions under which a correct program may fail come first, followed * This file is included multiple times to declare and define a structure
* by messages that indicate an incorrect program or system failure. The * with these messages, and then to define a lookup table translating
* macro E() along with double-inclusion is used to ensure that ordering * error codes to offsets of corresponding fields in the structure. */
* of the strings remains synchronized. */
E(0, "No error information")
E(EILSEQ, "Illegal byte sequence") E(EILSEQ, "Illegal byte sequence")
E(EDOM, "Domain error") E(EDOM, "Domain error")
@ -101,5 +102,3 @@ E(EDQUOT, "Quota exceeded")
E(ENOMEDIUM, "No medium found") E(ENOMEDIUM, "No medium found")
E(EMEDIUMTYPE, "Wrong medium type") E(EMEDIUMTYPE, "Wrong medium type")
E(EMULTIHOP, "Multihop attempted") E(EMULTIHOP, "Multihop attempted")
E(0, "No error information")

View file

@ -1,30 +1,41 @@
#include <errno.h> #include <errno.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include "locale_impl.h" #include "locale_impl.h"
#define E(a,b) ((unsigned char)a), /* mips has one error code outside of the 8-bit range due to a
static const unsigned char errid[] = { * historical typo, so we just remap it. */
#if EDQUOT==1133
#define EDQUOT_ORIG 1133
#undef EDQUOT
#define EDQUOT 109
#endif
static const struct errmsgstr_t {
#define E(n, s) char str##n[sizeof(s)];
#include "__strerror.h" #include "__strerror.h"
#undef E
} errmsgstr = {
#define E(n, s) s,
#include "__strerror.h"
#undef E
}; };
#undef E static const unsigned short errmsgidx[] = {
#define E(a,b) b "\0" #define E(n, s) [n] = offsetof(struct errmsgstr_t, str##n),
static const char errmsg[] =
#include "__strerror.h" #include "__strerror.h"
; #undef E
};
char *__strerror_l(int e, locale_t loc) char *__strerror_l(int e, locale_t loc)
{ {
const char *s; const char *s;
int i; #ifdef EDQUOT_ORIG
/* mips has one error code outside of the 8-bit range due to a if (e==EDQUOT) e=0;
* historical typo, so we just remap it. */ else if (e==EDQUOT_ORIG) e=EDQUOT;
if (EDQUOT==1133) { #endif
if (e==109) e=-1; if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0;
else if (e==EDQUOT) e=109; s = (char *)&errmsgstr + errmsgidx[e];
}
for (i=0; errid[i] && errid[i] != e; i++);
for (s=errmsg; i; s++, i--) for (; *s; s++);
return (char *)LCTRANS(s, LC_MESSAGES, loc); return (char *)LCTRANS(s, LC_MESSAGES, loc);
} }