source: rtems/cpukit/libcsupport/src/error.c @ 92119ed

4.115
Last change on this file since 92119ed was 1d33ecab, checked in by Joel Sherrill <joel.sherrill@…>, on 06/28/10 at 22:13:55

2010-06-28 Joel Sherrill <joel.sherrill@…>

  • libcsupport/include/rtems/error.h, libcsupport/src/error.c: Clean up so rtems_panic() can be a noreturn method. This eliminates some unreachable and thus untestable code.
  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 *  report errors and panics to RTEMS' stderr.
3 *  Currently just used by RTEMS monitor.
4 *
5 *  $Id$
6 */
7
8#if HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12/*
13 * These routines provide general purpose error reporting.
14 * rtems_error reports an error to stderr and allows use of
15 * printf style formatting.  A newline is appended to all messages.
16 *
17 * error_flag can be specified as any of the following:
18 *
19 *  RTEMS_ERROR_ERRNO       -- include errno text in output
20 *  RTEMS_ERROR_PANIC       -- halts local system after output
21 *  RTEMS_ERROR_ABORT       -- abort after output
22 *
23 * It can also include a rtems_status value which can be OR'd
24 * with the above flags. *
25 *
26 * EXAMPLE
27 *  #include <rtems.h>
28 *  #include <rtems/error.h>
29 *  rtems_error(0, "stray interrupt %d", intr);
30 *
31 * EXAMPLE
32 *        if ((status = rtems_task_create(...)) != RTEMS_SUCCCESSFUL)
33 *        {
34 *            rtems_error(status | RTEMS_ERROR_ABORT,
35 *                        "could not create task");
36 *        }
37 *
38 * EXAMPLE
39 *        if ((fd = open(pathname, O_RDNLY)) < 0)
40 *        {
41 *            rtems_error(RTEMS_ERROR_ERRNO, "open of '%s' failed", pathname);
42 *            goto failed;
43 *        }
44 */
45
46#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
47#include <rtems.h>
48
49#include <rtems/error.h>
50#include <rtems/assoc.h>
51#include <inttypes.h>
52#include <stdio.h>
53#include <stdarg.h>
54#include <errno.h>
55#include <stdlib.h>
56#include <string.h>
57#include <unistd.h>     /* _exit() */
58
59int          rtems_panic_in_progress;
60
61const rtems_assoc_t rtems_status_assoc[] = {
62  { "successful completion",              RTEMS_SUCCESSFUL, 0 },
63  { "returned from a thread",             RTEMS_TASK_EXITTED, 0 },
64  { "multiprocessing not configured",     RTEMS_MP_NOT_CONFIGURED, 0 },
65  { "invalid object name",                RTEMS_INVALID_NAME, 0 },
66  { "invalid object id",                  RTEMS_INVALID_ID, 0 },
67  { "too many",                           RTEMS_TOO_MANY, 0 },
68  { "timed out waiting",                  RTEMS_TIMEOUT, 0 },
69  { "object deleted while waiting",       RTEMS_OBJECT_WAS_DELETED, 0 },
70  { "specified size was invalid",         RTEMS_INVALID_SIZE, 0 },
71  { "address specified is invalid",       RTEMS_INVALID_ADDRESS, 0 },
72  { "number was invalid",                 RTEMS_INVALID_NUMBER, 0 },
73  { "item has not been initialized",      RTEMS_NOT_DEFINED, 0 },
74  { "resources still outstanding",        RTEMS_RESOURCE_IN_USE, 0 },
75  { "request not satisfied",              RTEMS_UNSATISFIED, 0 },
76  { "thread is in wrong state",           RTEMS_INCORRECT_STATE, 0 },
77  { "thread already in state",            RTEMS_ALREADY_SUSPENDED, 0 },
78  { "illegal on calling thread",          RTEMS_ILLEGAL_ON_SELF, 0 },
79  { "illegal for remote object",          RTEMS_ILLEGAL_ON_REMOTE_OBJECT, 0 },
80  { "called from wrong environment",      RTEMS_CALLED_FROM_ISR, 0 },
81  { "invalid thread priority",            RTEMS_INVALID_PRIORITY, 0 },
82  { "invalid date/time",                  RTEMS_INVALID_CLOCK, 0 },
83  { "invalid node id",                    RTEMS_INVALID_NODE, 0 },
84  { "directive not configured",           RTEMS_NOT_CONFIGURED, 0 },
85  { "not owner of resource",              RTEMS_NOT_OWNER_OF_RESOURCE , 0 },
86  { "directive not implemented",          RTEMS_NOT_IMPLEMENTED, 0 },
87  { "RTEMS inconsistency detected",       RTEMS_INTERNAL_ERROR, 0 },
88  { "could not get enough memory",        RTEMS_NO_MEMORY, 0 },
89  { "driver IO error",                    RTEMS_IO_ERROR, 0 },
90  { "internal multiprocessing only",      THREAD_STATUS_PROXY_BLOCKING, 0 },
91  { 0, 0, 0 },
92};
93
94
95const char *rtems_status_text(
96  rtems_status_code status
97)
98{
99  return rtems_assoc_name_by_local(rtems_status_assoc, status);
100}
101
102
103static int rtems_verror(
104  rtems_error_code_t  error_flag,
105  const char         *printf_format,
106  va_list             arglist
107)
108{
109  int               local_errno = 0;
110  int               chars_written = 0;
111  rtems_status_code status;
112
113  if (error_flag & RTEMS_ERROR_PANIC) {
114    if (rtems_panic_in_progress++)
115      _Thread_Disable_dispatch();       /* disable task switches */
116
117    /* don't aggravate things */
118    if (rtems_panic_in_progress > 2)
119      return 0;
120  }
121
122  (void) fflush(stdout);            /* in case stdout/stderr same */
123
124  status = error_flag & ~RTEMS_ERROR_MASK;
125  if (error_flag & RTEMS_ERROR_ERRNO)     /* include errno? */
126    local_errno = errno;
127
128  #if defined(RTEMS_MULTIPROCESSING)
129    if (_System_state_Is_multiprocessing)
130      fprintf(stderr, "[%" PRIu32 "] ", _Configuration_MP_table->node);
131  #endif
132
133  chars_written += vfprintf(stderr, printf_format, arglist);
134
135  if (status)
136    chars_written +=
137      fprintf(stderr, " (status: %s)", rtems_status_text(status));
138
139  if (local_errno) {
140    if ((local_errno > 0) && *strerror(local_errno))
141      chars_written += fprintf(stderr, " (errno: %s)", strerror(local_errno));
142    else
143      chars_written += fprintf(stderr, " (unknown errno=%d)", local_errno);
144  }
145
146  chars_written += fprintf(stderr, "\n");
147
148  (void) fflush(stderr);
149
150  return chars_written;
151}
152
153
154/*
155 * Report an error.
156 * error_flag is as above; printf_format is a normal
157 * printf(3) format string, with its concommitant arguments.
158 *
159 * Returns the number of characters written.
160 */
161
162int rtems_error(
163  rtems_error_code_t error_flag,
164  const char *printf_format,
165  ...
166)
167{
168  va_list arglist;
169  int chars_written;
170
171  va_start(arglist, printf_format);
172  chars_written = rtems_verror(error_flag, printf_format, arglist);
173  va_end(arglist);
174
175  if (error_flag & RTEMS_ERROR_PANIC) {
176    rtems_error(0, "fatal error, exiting");
177    _exit(errno);
178  }
179  if (error_flag & RTEMS_ERROR_ABORT) {
180    rtems_error(0, "fatal error, aborting");
181    abort();
182  }
183
184  return chars_written;
185}
186
187/*
188 * rtems_panic is shorthand for rtems_error(RTEMS_ERROR_PANIC, ...)
189 */
190
191void rtems_panic(
192  const char *printf_format,
193  ...
194)
195{
196  va_list arglist;
197
198  va_start(arglist, printf_format);
199  (void) rtems_verror(RTEMS_ERROR_PANIC, printf_format, arglist);
200  va_end(arglist);
201
202  rtems_error(0, "fatal error, exiting");
203  _exit(errno);
204}
Note: See TracBrowser for help on using the repository browser.