Annotation of coherent/b/STREAMS/conf/streams/src/cmn_err.c, revision 1.1.1.1

1.1       root        1: #define        _DDI_DKI        1
                      2: #define        _SYSV4          1
                      3: 
                      4: /*
                      5:  * Error-reporting code....
                      6:  */
                      7: 
                      8: /*
                      9:  *-IMPORTS:
                     10:  *     <common/ccompat.h>
                     11:  *             __PROTO ()
                     12:  *             __USE_PROTO__
                     13:  *             __ARGS ()
                     14:  *     <common/xdebug.h>
                     15:  *             __LOCAL__
                     16:  *     <sys/inline.h>
                     17:  *             splhi ()
                     18:  *             splx ()
                     19:  *     <sys/ksynch.h>
                     20:  *             lock_t
                     21:  *             LOCK ()
                     22:  *             LOCK_ALLOC ()
                     23:  *             UNLOCK ()
                     24:  *     <common/_null.h>
                     25:  *             NULL
                     26:  *     <limits.h>
                     27:  *             CHAR_BIT
                     28:  *     <stdarg.h>
                     29:  *             va_list
                     30:  *             va_start ()
                     31:  *             va_arg ()
                     32:  *             va_end ()
                     33:  *
                     34:  *-PRIVATE DEPENDENCIES:
                     35:  *     _put_console ()
                     36:  *     _put_putbuf ()
                     37:  */
                     38: 
                     39: #include <common/ccompat.h>
                     40: #include <common/xdebug.h>
                     41: #include <sys/inline.h>
                     42: #include <sys/ksynch.h>
                     43: #include <common/_null.h>
                     44: #include <sys/ddi.h>
                     45: 
                     46: #include <limits.h>
                     47: #include <stdarg.h>
                     48: 
                     49: #include <sys/cmn_err.h>
                     50: 
                     51: #ifdef __MSDOS__
                     52: 
                     53: #include <process.h>
                     54: 
                     55: #endif
                     56: 
                     57: 
                     58: /*
                     59:  *-GLOBAL VARIABLES:
                     60:  *      conlock                lock to single-thread console output
                     61:  *     putlock         lock to single-thread putbuf output
                     62:  */
                     63: 
                     64: /*
                     65:  * Note that these locks are always acquired in the order conlock -> putlock;
                     66:  * this is required to ensure that the system remains deadlock-free. The
                     67:  * hierarchy mechanism is used to enforce this constraint.
                     68:  *
                     69:  * We use the user namespace for these since if they are actually made public
                     70:  * by definitions in <common/xdebug.h> then they will still not conflict with
                     71:  * user symbols (ie, we assume that this module is an "implementation"
                     72:  * module...
                     73:  */
                     74: 
                     75: __LOCAL__ lock_t                     * _conlock;
                     76: __LOCAL__ lock_t             * _putlock;
                     77: 
                     78: 
                     79: /*
                     80:  * The following are not global variables, they're static constants.
                     81:  */
                     82: 
                     83: static char * message_level [] = {
                     84:        "",
                     85:        "NOTICE : ",
                     86:        "WARNING : ",
                     87:        "PANIC : ",
                     88:        "<INVALID ERROR LEVEL> : "
                     89: };
                     90: 
                     91: 
                     92: /*
                     93:  * The following external function declarations exist for internal layering
                     94:  * purposes and do not appear in any headers. The names begin with a single
                     95:  * underscore (reserved for the user with internal linkage, reserved for the
                     96:  * system with external linkage) so as not to conflict with any user-defined
                     97:  * symbol names.
                     98:  *
                     99:  * If you find this use of the implementation namespace distasteful, then
                    100:  * you'll have to move the function definitions in here.
                    101:  *
                    102:  * Note also that these functions will have the default language linkage
                    103:  * for the translator, ie we allow these functions to be mangled C++. This
                    104:  * constrains them to be produced by the same translator used for this
                    105:  * module.
                    106:  */
                    107: 
                    108: #if    __COHERENT__
                    109: void           putchar         __PROTO ((int _c));
                    110: #define        _put_console(c)         putchar (c)
                    111: #else
                    112: void           _put_console    __PROTO ((unsigned char _outch));
                    113: #endif
                    114: 
                    115: void           _put_putbuf     __PROTO ((unsigned char _outch));
                    116: 
                    117: 
                    118: /*
                    119:  *-STATUS:
                    120:  *     DDI/DKI
                    121:  *
                    122:  *-NAME:
                    123:  *     cmn_err ()      display an error message or panic the system
                    124:  *
                    125:  *-SYNOPSIS:
                    126:  *     #include <sys/cmn_err.h>
                    127:  *
                    128:  *     void cmn_err (int level, char * format, ...);
                    129:  *
                    130:  *-ARGUMENTS:
                    131:  *     level           "level" indicates the severity of the error condition.
                    132:  *                     Valid levels are:
                    133:  *                     CE_CONT used to continue a previous message or to
                    134:  *                             display an informative message not connected
                    135:  *                             with an error.
                    136:  *                     CE_NOTE used to display a message preceded with
                    137:  *                             NOTICE:. This message is used to report system
                    138:  *                             events that do not necessarily require action,
                    139:  *                             by may interest the system administrator. For
                    140:  *                             example, a message saying that a sector on a
                    141:  *                             disk needs to be accessed repeatedly before it
                    142:  *                             can be accessed correctly might be noteworthy.
                    143:  *                     CE_WARN use to display a message preceded with
                    144:  *                             WARNING:. This message is used to report
                    145:  *                             system events that require immediate
                    146:  *                             attention, such as those where if an action is
                    147:  *                             not taken, the system may panic. For example,
                    148:  *                             where a peripheral device does not initialize
                    149:  *                             correctly, this level should be used.
                    150:  *                     CE_PANIC used to display a message preceded by PANIC:,
                    151:  *                             and panic the system. Drivers should use this
                    152:  *                             level only for debugging or in the case of
                    153:  *                             severe errors that indicate that the system
                    154:  *                             cannot continue to function. This level halts
                    155:  *                             processing.
                    156:  *
                    157:  *     format          The message to be displayed. By default, the message
                    158:  *                     is sent both to the system console and to the circular
                    159:  *                     kernel buffer, "putbuf". If the first character in
                    160:  *                     "format" is an exclamation point ("!"), the message
                    161:  *                     goes only to "putbuf". If the first character in
                    162:  *                     "format" is a circumflex ("^"), the message goes only
                    163:  *                     to the console. The size of the circular buffer
                    164:  *                     "putbuf" is defined by the kernel variable "putbufsz".
                    165:  *                     Driver developers or administrators can read the
                    166:  *                     "putbuf" buffer using appropriate debugging or
                    167:  *                     administrative tools.
                    168:  *
                    169:  *                     cmn_err () appends '\n' to each "format" string, even
                    170:  *                     when a message is sent to "putbuf", except when level
                    171:  *                     is CE_CONT.
                    172:  *
                    173:  *                     Valid conversion specifications are %s, %u, %d, %o,
                    174:  *                     and %x. The cmn_err () function is otherwise similar
                    175:  *                     to the printf () library subroutine is its
                    176:  *                     interpretation of the "format" string, except that
                    177:  *                     cmn_err () does not accept length specifications in
                    178:  *                     conversion specifications. For example, %3d is invalid
                    179:  *                     and will be treated as a literal string, resulting in
                    180:  *                     a mismatch of arguments.
                    181:  *
                    182:  *     ...             the set of arguments passed with the message being
                    183:  *                     displayed. Any argument within the range of supported
                    184:  *                     conversion specifications can be passed.
                    185:  *
                    186:  *-DESCRIPTION:
                    187:  *     cmn_err () displays a specified message on the console and/or stores
                    188:  *     it in the kernel buffer "putbuf". cmn_err () can also panic the
                    189:  *     system.
                    190:  *
                    191:  *     At times a driver may encounter error conditions requiring the
                    192:  *     attention of a system console monitor. These conditions may mean
                    193:  *     halting the system; however, this must be done with caution. Except
                    194:  *     during the debugging stage, or in the case of a serious, unrecoverable
                    195:  *     error, a driver should never stop the system.
                    196:  *
                    197:  *     The cmn_err () function with the CE_CONT argument can be used by
                    198:  *     driver developers as a driver code debugging tool. However, using
                    199:  *     cmn_err () in this capacity can change system timing characteristics.
                    200:  *
                    201:  *-NOTES:
                    202:  *     Does not sleep.
                    203:  *
                    204:  *     If "level" is CE_PANIC, then driver defined basic locks, read/write
                    205:  *     locks, and sleep locks may not be held across calls to this function.
                    206:  *     For other levels, locks may be held.
                    207:  */
                    208: 
                    209: enum { OUT_CONSOLE = 1,
                    210:        OUT_PUTBUF = 2,
                    211:        OUT_LONG = 4,
                    212:        OUT_SHORT = 8,
                    213:        OUT_SIGNED = 16
                    214: };
                    215: 
                    216: typedef        char          * _string_t;      /* for va_arg () */
                    217: typedef unsigned short         _ushort_t;
                    218: typedef unsigned int   _uint_t;
                    219: typedef unsigned long  _ulong_t;
                    220: 
                    221: 
                    222: #if    __USE_PROTO__
                    223: void (cmn_err) (int level, char * format, ...)
                    224: #else
                    225: void
                    226: cmn_err __ARGS ((level, format))
                    227: int            level;
                    228: char         * format;
                    229: #endif
                    230: {
                    231:        /*
                    232:         * The following local data is used for converting numeric data to
                    233:         * strings. Numbuf is defined such that it is large enough to hold
                    234:         * the maximum number of digits that could be generated from any
                    235:         * conversion specification (currently, the longest possible spec is
                    236:         * %lo).
                    237:         */
                    238: 
                    239:        char            numbuf [(sizeof (long) * CHAR_BIT  + 2) / 3 + 1];
                    240:        char          * numptr;
                    241:        int             radix;
                    242:        long            svalue;
                    243:        unsigned long   value;
                    244: 
                    245:        va_list         args;
                    246: 
                    247:        unsigned        output;         /* who to output to */
                    248: 
                    249:        pl_t            con_pl;         /* for locking */
                    250:        pl_t            put_pl;
                    251: 
                    252: 
                    253:        if (format == NULL)
                    254:                format = "<cmn_err: no error message was supplied>";
                    255: 
                    256:        if (* format == '!') {
                    257:                format ++;
                    258:                output = OUT_PUTBUF;
                    259:        } else if (* format == '^') {
                    260:                format ++;
                    261:                output = OUT_CONSOLE;
                    262:        } else
                    263:                output = OUT_PUTBUF | OUT_CONSOLE;
                    264: 
                    265: 
                    266:        /*
                    267:         * Before we generate any output, we should lock the console/putbuf
                    268:         * so that our messages won't get interspersed with diagnostic output
                    269:         * from interrupt handlers or other CPUs.
                    270:         *
                    271:         * If we get called before the locks have been allocated, proceed
                    272:         * at the highest interrupt priority as a fallback.
                    273:         */
                    274: 
                    275:        if (_conlock != NULL) {
                    276:                if ((output & OUT_CONSOLE) != 0)
                    277:                        con_pl = LOCK (_conlock, plhi);
                    278: 
                    279:                if ((output & OUT_PUTBUF) != 0)
                    280:                        put_pl = LOCK (_putlock, plhi);
                    281:        } else
                    282:                con_pl = splhi ();
                    283: 
                    284: 
                    285:        /*
                    286:         * Check that the level argument is reasonable.
                    287:         */
                    288: 
                    289:        if (level < CE_CONT || level > CE_PANIC)
                    290:                level = CE_INVALID;
                    291: 
                    292: 
                    293:        /*
                    294:         * We should think about generating the date and as accurate a time
                    295:         * reading as possible along with the fixed-text header.
                    296:         *
                    297:         * For now, we'll just generate some fixed text.
                    298:         */
                    299: 
                    300:        numptr = message_level [level];
                    301: 
                    302:        while (* numptr != 0) {
                    303:                if ((output & OUT_CONSOLE) != 0)
                    304:                        _put_console (* numptr);
                    305: 
                    306:                if ((output & OUT_PUTBUF) != 0)
                    307:                        _put_putbuf (* numptr);
                    308: 
                    309:                numptr ++;
                    310:        }
                    311: 
                    312: 
                    313:        /*
                    314:         * Now start generating formatted output.
                    315:         *
                    316:         * The manual page quoted in the function header doesn't say whether
                    317:         * the 'l' and 'h' modifiers are available for conversion
                    318:         * specifications. We'll implement them anyway.
                    319:         */
                    320: 
                    321:        va_start (args, format);
                    322: 
                    323:        while (* format != 0) {
                    324:                if (format [0] == '%') {
                    325:                        /*
                    326:                         * Process the conversion-specifications.
                    327:                         *
                    328:                         * We temporarily borrow 'radix' as a temporary for
                    329:                         * working out how long the conversion specification
                    330:                         * is.
                    331:                         */
                    332: 
                    333: 
                    334:                        output &= ~ (OUT_LONG | OUT_SHORT | OUT_SIGNED);
                    335: 
                    336:                        radix = 2;
                    337: 
                    338:                        if (format [radix - 1] == 'h') {
                    339:                                output |= OUT_SHORT;
                    340:                                radix ++;
                    341:                        } else if (format [radix - 1] == 'l') {
                    342:                                output |= OUT_LONG;
                    343:                                radix ++;
                    344:                        }
                    345: 
                    346:                        switch ((format += radix) [-1]) {
                    347: 
                    348:                        case 's':
                    349:                                numptr = va_arg (args, _string_t);
                    350:                                goto out_string;
                    351: 
                    352:                        case 'd':
                    353:                                /*
                    354:                                 * This is the only signed numeric conversion
                    355:                                 * specification, so we process the sign here.
                    356:                                 */
                    357: 
                    358:                                radix = 10;
                    359: 
                    360:                                if ((output & OUT_SHORT) != 0)
                    361:                                        svalue = (short) va_arg (args, int);
                    362:                                else if ((output & OUT_LONG) != 0)
                    363:                                        svalue = va_arg (args, long);
                    364:                                else
                    365:                                        svalue = va_arg (args, int);
                    366: 
                    367:                                if (svalue < 0) {
                    368:                                        if ((output & OUT_CONSOLE) != 0)
                    369:                                                _put_console ('-');
                    370: 
                    371:                                        if ((output & OUT_PUTBUF) != 0)
                    372:                                                _put_putbuf ('-');
                    373: 
                    374:                                        svalue = - svalue;
                    375:                                }
                    376: 
                    377:                                output |= OUT_SIGNED;
                    378:                                break;
                    379: 
                    380:                        case 'o':
                    381:                                radix = 8;
                    382:                                break;
                    383: 
                    384:                        case 'u':
                    385:                                radix = 10;
                    386:                                break;
                    387: 
                    388:                        case 'x':
                    389:                                radix = 16;
                    390:                                break;
                    391: 
                    392:                        case '%':
                    393:                                /*
                    394:                                 * Special case: %% -> %
                    395:                                 */
                    396: 
                    397:                                format -= 1;
                    398:                                goto bad_format;
                    399: 
                    400:                        default:
                    401:                                /*
                    402:                                 * It's not a valid conversion, so we back
                    403:                                 * up "format".
                    404:                                 */
                    405:                                format -= radix;
                    406:                                goto bad_format;
                    407:                        }
                    408: 
                    409: 
                    410:                        /*
                    411:                         * All numeric conversions come here.
                    412:                         */
                    413: 
                    414:                        if ((output & OUT_SIGNED) != 0)
                    415:                                value = svalue;
                    416:                        else if ((output & OUT_SHORT) != 0)
                    417:                                value = (_ushort_t) va_arg (args, _uint_t);
                    418:                        else if ((output & OUT_LONG) != 0)
                    419:                                value = va_arg (args, _ulong_t);
                    420:                        else
                    421:                                value = va_arg (args, _uint_t);
                    422: 
                    423: 
                    424:                        /*
                    425:                         * Now we generate the output digits one-at-a-time in
                    426:                         * reverse order. We step back from the end of the
                    427:                         * conversion buffer so that at the end of the
                    428:                         * conversion process we have a C string with the
                    429:                         * characters in a 'normal' order.
                    430:                         *
                    431:                         * (This allows the final output loop to be folded in
                    432:                         *  with the string-output code).
                    433:                         */
                    434: 
                    435:                        numptr = & numbuf [sizeof (numbuf) - 1];
                    436: 
                    437:                        * numptr = 0;   /* terminate the output string */
                    438: 
                    439:                        do {
                    440:                                int     rem = (int) (value % radix);
                    441:                                value /= radix;
                    442: 
                    443:                                * -- numptr = (rem < 10) ? rem + '0' :
                    444:                                                           rem + 'a' - 10;
                    445:                        } while (value > 0);
                    446: 
                    447: 
                    448:                        /*
                    449:                         * Copy temporary numeric-conversion string or
                    450:                         * user-supplied string argument to the output.
                    451:                         */
                    452: 
                    453: out_string:
                    454:                        while (* numptr != 0) {
                    455:                                if ((output & OUT_CONSOLE) != 0)
                    456:                                        _put_console (* numptr);
                    457: 
                    458:                                if ((output & OUT_PUTBUF) != 0)
                    459:                                        _put_putbuf (* numptr);
                    460: 
                    461:                                numptr ++;
                    462:                        }
                    463:                        continue;
                    464:                }
                    465: bad_format:
                    466:                if ((output & OUT_CONSOLE) != 0)
                    467:                        _put_console (* format);
                    468: 
                    469:                if ((output & OUT_PUTBUF) != 0)
                    470:                        _put_putbuf (* format);
                    471: 
                    472:                format ++;
                    473:        }
                    474: 
                    475: 
                    476:        /*
                    477:         * Output a trailing '\n' unless the level is CE_CONT
                    478:         */
                    479: 
                    480:        if (level != CE_CONT) {
                    481:                if ((output & OUT_CONSOLE) != 0)
                    482:                        _put_console ('\n');
                    483: 
                    484:                if ((output & OUT_PUTBUF) != 0)
                    485:                        _put_putbuf ('\n');
                    486:        }
                    487: 
                    488: 
                    489:        /*
                    490:         * Now release the locks we acquired, and consider returning to the
                    491:         * caller (unless this is a panic).
                    492:         *
                    493:         * A minor point: if we panic, we should release our locks but
                    494:         * without causing interrupts to be enabled on this CPU; in order to
                    495:         * do this we kludge "con_pl" and "put_pl" to be "plhi";
                    496:         */
                    497: 
                    498:        if (level >= CE_PANIC)          /* panic on an invalid level */
                    499:                con_pl = put_pl = plhi;
                    500: 
                    501: 
                    502:        if (_conlock != NULL) {
                    503:                if ((output & OUT_PUTBUF) != 0)
                    504:                        UNLOCK (_putlock, put_pl);
                    505: 
                    506:                if ((output & OUT_CONSOLE) != 0)
                    507:                        LOCK (_conlock, con_pl);
                    508:        } else
                    509:                (void) splx (con_pl);
                    510: 
                    511: 
                    512:        if (level >= CE_PANIC) {
                    513:                /*
                    514:                 * This CPU is shutting down. The actions to be taken here
                    515:                 * are so highly system-specific that we'll just throw them
                    516:                 * into another file.
                    517:                 */
                    518: 
                    519: #ifdef __MSDOS__
                    520:                splx (plbase);
                    521: 
                    522:                exit (3);       /* call atexit () functions */
                    523: #endif
                    524:        }
                    525: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.