logLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:17k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* logLib.c - message logging library */
  2. /* Copyright 1984-1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03l,13may02,cyr  fix SPR 32358 documentation clarification on logMsg
  8. 03k,29oct01,cyr  doc:doc: correct SPR 7113 logMsg
  9. 03j,30oct95,ism  added simsolaris support
  10. 03i,09nov94,ms   undid 03h. Bumped stack size for SIMSPARC.
  11. 03h,17jul94,ms   jacked up the stack size for VxSim/HPPA.
  12. 03g,24aug93,dvs  added reset of logFdFromRlogin.
  13. 03f,23aug93,dvs  fixed logFdSet() for rlogin sessions (SPR #2212).
  14. 03e,15feb93,jdi  fixed doc for logMsg() to mention fixed number of args.
  15. 03d,21jan93,jdi  documentation cleanup for 5.1.
  16. 03c,13nov92,jcf  added _func_logMsg initialization.  added include semLibP.h.
  17. 03b,17jul92,gae  reverted to 02x -- eliminating stdargs change.
  18.  Documentation sprs #600 and #1148 fixed.  Checked
  19.  for null format specifier.
  20. 03a,18jul92,smb  Changed errno.h to errnoLib.h.
  21. 02z,26may92,rrr  the tree shuffle
  22. 02y,04mar92,gae  Used stdargs for logMsg, no longer fixed at 6 parameters.
  23.  Allowed messages to be dropped via global var. logMsgTimeout.
  24.  Reduced stack size from 5000 to 3000.
  25.  Checked for null format specifier.
  26.  Fixed spr #600 (documentation of logMsg).
  27.  Fixed spr #1138 (printing of floating point numbers).
  28.  Fixed spr #1148 (document use of message queues)
  29. 02x,10dec91,gae  added includes for ANSI.
  30. 02w,04oct91,rrr  passed through the ansification filter
  31.                   -changed functions to ansi style
  32.   -changed VOID to void
  33.   -changed copyright notice
  34. 02v,01aug91,yao  changed to check for dead task in logTask(). added missing
  35.  arg to lprintf() call.
  36. 02u,10jun91,del  changed MAX_ARGS to MAX_LOGARGS to silence redef warning.
  37. 02t,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  38.  doc review by dnw.
  39. 02s,11feb91,jaa  documentation cleanup.
  40. 02r,08oct90,dnw  lint
  41. 02q,05oct90,dnw  changed to new msgQ interface.
  42. 02p,10aug90,dnw  changed declaration for logMsg from void to int.
  43.  added include of logLib.h.
  44. 02o,10aug90,kdl  added forward declaration for lprintf.
  45. 02n,19jul90,dnw  changed to use message queue instead of pipe
  46.  changed logTask stack from 10k to 5k
  47.  spr 641: changed logMsg to return number of bytes written to
  48. msg q or EOF if error writing
  49.  improved module and logMsg doc, esp about volitile args
  50. 02m,10jul90,dnw  logTask no longer dies with bus error when printing msg from
  51.    interrupt level (fixed to not call taskName(-1))
  52.  changed to use INT_CONTEXT() instead of intContext()
  53. 02l,26jun90,jcf  changed logTask semaphore to mutex.
  54. 02k,15apr90,jcf  changed logTask name to tLogTask.
  55. 02j,14mar90,jdi  documentation cleanup.
  56. 02i,16sep88,ecs  bumped logTaskStackSize from 2000 to 10000.
  57.  removed architectural assumption from logMsg.
  58. 02h,14jun89,gae  changed the format of the logMsg's to be more intelligible.
  59. 02g,07jul88,jcf  made logShow global but NOMANUAL, so lint would let up.
  60. 02f,22jun88,dnw  name tweaks.
  61. 02e,06jun88,dnw  changed taskSpawn/taskCreate args.
  62. 02d,30may88,dnw  changed to v4 names.
  63. 02c,23apr88,jcf  changed semaphores for new semLib.
  64. 02b,05apr88,gae  changed fprintf() to fdprintf().  Added debug rtn logShow().
  65. 02a,26jan88,jcf  made kernel independent.
  66. 01q,14dec87,gae  changed logMsg() to not have multiple argument decl's for
  67.    parsing by the C interface generator.
  68. 01p,16nov87,ecs  documentation.
  69. 01o,03nov87,dnw  changed to let system pick logTask id;
  70.    now available in logTaskId.
  71. 01n,14oct87,gae  added log{Add,Del}Fd(), allowing multiple logging fds.
  72.  removed NOT_GENERIC stuff.
  73. 01m,24mar87,jlf  documentation
  74. 01l,21dec86,dnw  changed to not get include files from default directories.
  75. 01k,31jul86,llk  uses new spawn
  76. 01j,09jul86,dnw  restored NOT_GENERIC stuff that got lost in v01i.
  77. 01i,01jul86,jlf  minor documentation
  78. 01h,09apr86,dnw  added call to vxSetTaskBreakable to make logTask unbreakable.
  79.  fixed documentation of logMsg().
  80. 01g,07apr86,dnw  increased logTsk stack from 1000 to 2000.
  81.  corrected errors in documentation.
  82.  added logSetFd().
  83. 01f,11mar86,jlf  changed GENERIC to NOT_GENERIC
  84. 01e,20jul85,jlf  documentation.
  85. 01d,04jan85,ecs  added an ARGSUSED to logMsg, got rid of 'housetime'.
  86. 01c,19sep84,jlf  cleaned up comments a little
  87. 01b,07sep84,jlf  added copyright notice and comments.
  88. 01a,28aug84,dnw  culled from fioLib and enhanced.
  89. */
  90. /*
  91. DESCRIPTION
  92. This library handles message logging.  It is usually used to display error
  93. messages on the system console, but such messages can also be sent to a
  94. disk file or printer.
  95. The routines logMsg() and logTask() are the basic components of the
  96. logging system.  The logMsg() routine has the same calling sequence as
  97. printf(), but instead of formatting and outputting the message directly,
  98. it sends the format string and arguments to a message queue.  The task
  99. logTask() waits for messages on this message queue.  It formats each
  100. message according to the format string and arguments in the message,
  101. prepends the ID of the sender, and writes it on one or more file
  102. descriptors that have been specified as logging output streams (by
  103. logInit() or subsequently set by logFdSet() or logFdAdd()).
  104. USE IN INTERRUPT SERVICE ROUTINES
  105. Because logMsg() does not directly cause output to I/O devices, but
  106. instead simply writes to a message queue, it can be called from an
  107. interrupt service routine as well as from tasks.  Normal I/O, such as
  108. printf() output to a serial port, cannot be done from an interrupt service
  109. routine.
  110. DEFERRED LOGGING
  111. Print formatting is performed within the context of logTask(), rather than
  112. the context of the task calling logMsg().  Since formatting can require
  113. considerable stack space, this can reduce stack sizes for tasks that only
  114. need to do I/O for error output.
  115. However, this also means that the arguments to logMsg() are not interpreted
  116. at the time of the call to logMsg(), but rather are interpreted at some
  117. later time by logTask().  This means that the arguments to logMsg() should
  118. not be pointers to volatile entities.  For example, pointers to dynamic or
  119. changing strings and buffers should not be passed as arguments to be formatted.
  120. Thus the following would not give the desired results:
  121. .ne 8
  122. .CS
  123.     doLog (which)
  124. {
  125. char string [100];
  126. strcpy (string, which ? "hello" : "goodbye");
  127. ...
  128. logMsg (string);
  129. }
  130. .CE
  131. By the time logTask() formats the message, the stack frame of the caller may
  132. no longer exist and the pointer <string> may no longer be valid.
  133. On the other hand, the following is correct since the string pointer passed
  134. to the logTask() always points to a static string:
  135. .CS
  136.     doLog (which)
  137. {
  138. char *string;
  139. string = which ? "hello" : "goodbye";
  140. ...
  141. logMsg (string);
  142. }
  143. .CE
  144. INITIALIZATION
  145. To initialize the message logging facilities, the routine logInit() must
  146. be called before calling any other routine in this module.  This is done
  147. by the root task, usrRoot(), in usrConfig.c.
  148. INCLUDE FILES: logLib.h
  149. SEE ALSO: msgQLib,
  150. .pG "I/O System"
  151. */
  152. /* LINTLIBRARY */
  153. #include "vxWorks.h"
  154. #include "errnoLib.h"
  155. #include "logLib.h"
  156. #include "ioLib.h"
  157. #include "taskLib.h"
  158. #include "semLib.h"
  159. #include "intLib.h"
  160. #include "msgQLib.h"
  161. #include "stdio.h"
  162. #include "private/semLibP.h"
  163. #include "private/funcBindP.h"
  164. #define MAX_LOGARGS 6 /* max args to log message */
  165. #define MAX_LOGFDS 5 /* max log fds */
  166. typedef struct /* LOG_MSG */
  167.     {
  168.     int id; /* ID of sending task */
  169.     char * fmt; /* pointer to format string */
  170.     int arg [MAX_LOGARGS]; /* args for format string */
  171.     } LOG_MSG;
  172. /* logTask parameters */
  173. int logTaskId = 0;
  174. int logTaskPriority = 0;
  175. int logTaskOptions = VX_UNBREAKABLE;
  176. #if    CPU_FAMILY == SIMSPARCSUNOS || CPU_FAMILY == SIMSPARCSOLARIS
  177. int logTaskStackSize    = 8000;
  178. #else  /* CPU_FAMILY != SIMSPARCSUNOS */
  179. int logTaskStackSize = 5000;
  180. #endif /* CPU_FAMILY == SIMSPARCSUNOS || CPU_FAMILY == SIMSPARCSOLARIS */
  181. int mutexOptionsLogLib = SEM_Q_FIFO | SEM_DELETE_SAFE; /* mutex options */
  182. int logFdFromRlogin = NONE; /* fd of pty for rlogin */
  183. /* local variables */
  184. LOCAL SEMAPHORE logFdSem; /* semaphore for accessing logFd's */
  185. LOCAL MSG_Q_ID logMsgQId = 0; /* ID of misg q to log task */
  186. LOCAL int logFd [MAX_LOGFDS]; /* output fd's used for logging */
  187. LOCAL int numLogFds = 0; /* number of active logging fd's */
  188. LOCAL int logMsgsLost = 0; /* count of log messages lost */
  189. /* forward static functions */
  190. static void lprintf (char *fmt, int arg1, int arg2, int arg3, int arg4,
  191.      int arg5, int arg6);
  192. /*******************************************************************************
  193. *
  194. * logInit - initialize message logging library
  195. *
  196. * This routine specifies the file descriptor to be used as the logging
  197. * device and the number of messages that can be in the logging queue.  If
  198. * more than <maxMsgs> are in the queue, they will be discarded.  A message
  199. * is printed to indicate lost messages.
  200. *
  201. * This routine spawns logTask(), the task-level portion of error logging.
  202. *
  203. * This routine must be called before any other routine in logLib.
  204. * This is done by the root task, usrRoot(), in usrConfig.c.
  205. *
  206. * RETURNS
  207. * OK, or ERROR if a message queue could not be created
  208. * or logTask() could not be spawned.
  209. */
  210. STATUS logInit
  211.     (
  212.     int fd,             /* file descriptor to use as logging device */
  213.     int maxMsgs         /* max. number of messages allowed in log queue */
  214.     )
  215.     {
  216.     if (logTaskId != 0)
  217. return (ERROR);         /* already called */
  218.     logMsgQId = msgQCreate (maxMsgs, sizeof (LOG_MSG), MSG_Q_FIFO);
  219.     if (logMsgQId == NULL)
  220. return (ERROR);
  221.     logTaskId = taskSpawn ("tLogTask", logTaskPriority,
  222.    logTaskOptions, logTaskStackSize,
  223.    (FUNCPTR)logTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  224.     if (logTaskId == ERROR)
  225. {
  226. /* XXX free message q? */
  227. return (ERROR);
  228. }
  229.    _func_logMsg = (FUNCPTR) logMsg;
  230.     semMInit (&logFdSem, mutexOptionsLogLib);
  231.     logFdSet (fd);
  232.     return (OK);
  233.     }
  234. /*******************************************************************************
  235. *
  236. * logMsg - log a formatted error message
  237. *
  238. * This routine logs a specified message via the logging task.  This
  239. * routine's syntax is similar to printf() -- a format string is followed
  240. * by arguments to format.  However, the logMsg() routine takes a char *
  241. * rather than a const char * and requires a fixed number of arguments
  242. * (6).
  243. *
  244. * The task ID of the caller is prepended to the specified message.
  245. *
  246. * SPECIAL CONSIDERATIONS
  247. * Because logMsg() does not actually perform the output directly to the
  248. * logging streams, but instead queues the message to the logging task,
  249. * logMsg() can be called from interrupt service routines.
  250. *
  251. * However, since the arguments are interpreted by the logTask() at the
  252. * time of actual logging, instead of at the moment when logMsg() is called,
  253. * arguments to logMsg() should not be pointers to volatile entities
  254. * (e.g., dynamic strings on the caller stack).
  255. *
  256. * logMsg() checks to see whether or not it is running in interupt context. 
  257. * If it is, it will not block.  However, if invoked from a task, it can 
  258. * cause the task to block.  
  259. *
  260. *
  261. * For more detailed information about the use of logMsg(), see the manual
  262. * entry for logLib.
  263. *
  264. * EXAMPLE
  265. * If the following code were executed by task 20:
  266. * .CS
  267. *     {
  268. *     name = "GRONK";
  269. *     num = 123;
  270. *
  271. *     logMsg ("ERROR - name = %s, num = %d.en", name, num, 0, 0, 0, 0);
  272. *     }
  273. * .CE
  274. * the following error message would appear on the system log:
  275. * .CS
  276. *     0x180400 (t20): ERROR - name = GRONK, num = 123.
  277. * .CE
  278. *
  279. * RETURNS: The number of bytes written to the log queue,
  280. * or EOF if the routine is unable to write a message.
  281. *
  282. * SEE ALSO: printf(), logTask()
  283. */
  284. int logMsg
  285.     (
  286.     char *fmt,  /* format string for print */
  287.     int arg1,   /* first of six required args for fmt */
  288.     int arg2,
  289.     int arg3,
  290.     int arg4,
  291.     int arg5,
  292.     int arg6
  293.     )
  294.     {
  295.     int timeout;
  296.     LOG_MSG msg;
  297.     if (INT_CONTEXT ())
  298. {
  299. msg.id = -1;
  300. timeout = NO_WAIT;
  301. }
  302.     else
  303. {
  304. msg.id = taskIdSelf ();
  305. timeout = WAIT_FOREVER;
  306. }
  307.     msg.fmt    = fmt;
  308.     msg.arg[0] = arg1;
  309.     msg.arg[1] = arg2;
  310.     msg.arg[2] = arg3;
  311.     msg.arg[3] = arg4;
  312.     msg.arg[4] = arg5;
  313.     msg.arg[5] = arg6;
  314.     if (msgQSend (logMsgQId, (char *) &msg, sizeof (msg), timeout,
  315.   MSG_PRI_NORMAL) != OK)
  316. {
  317. ++logMsgsLost;
  318. return (EOF);
  319. }
  320.     return (sizeof (msg));
  321.     }
  322. /*******************************************************************************
  323. *
  324. * logFdSet - set the primary logging file descriptor
  325. *
  326. * This routine changes the file descriptor where messages from logMsg() 
  327. * are written, allowing the log device to be changed from the default
  328. * specified by logInit().  It first removes the old file descriptor (if 
  329. * one had been previously set) from the log file descriptor list, then 
  330. * adds the new <fd>.
  331. *
  332. * The old logging file descriptor is not closed or affected by this call; 
  333. * it is simply no longer used by the logging facilities.
  334. *
  335. * RETURNS: N/A
  336. *
  337. * SEE ALSO: logFdAdd(), logFdDelete()
  338. */
  339. void logFdSet
  340.     (
  341.     int fd      /* file descriptor to use as logging device */
  342.     )
  343.     {
  344.     static int oldLogFd = NONE;
  345.     if (oldLogFd != NONE)
  346. logFdDelete (oldLogFd);
  347.     /* if we are called from an rlogin session, remove pty fd from log fd list */
  348.     if (logFdFromRlogin != NONE)
  349. {
  350. logFdDelete (logFdFromRlogin);
  351. logFdFromRlogin = NONE; /* reset since its deleted from list */
  352. }
  353.     if (logFdAdd (fd) == OK)
  354. oldLogFd = fd;
  355.     else
  356. oldLogFd = NONE;
  357.     }
  358. /*******************************************************************************
  359. *
  360. * logFdAdd - add a logging file descriptor
  361. *
  362. * This routine adds to the log file descriptor list another file descriptor
  363. * <fd> to which messages will be logged.  The file descriptor must be a 
  364. * valid open file descriptor.
  365. *
  366. * RETURNS:
  367. * OK, or ERROR if the allowable number of additional logging file descriptors
  368. * (5) is exceeded.
  369. *
  370. * SEE ALSO: logFdDelete()
  371. */
  372. STATUS logFdAdd
  373.     (
  374.     int fd      /* file descriptor for additional logging device */
  375.     )
  376.     {
  377.     semTake (&logFdSem, WAIT_FOREVER);
  378.     if ((numLogFds + 1) > MAX_LOGFDS)
  379. {
  380. semGive (&logFdSem);
  381. /* XXX errnoSet (S_logLib_TOO_MANY_LOGGING_FDS); */
  382. return (ERROR);
  383. }
  384.     logFd [numLogFds++] = fd;
  385.     semGive (&logFdSem);
  386.     return (OK);
  387.     }
  388. /*******************************************************************************
  389. *
  390. * logFdDelete - delete a logging file descriptor
  391. *
  392. * This routine removes from the log file descriptor list a logging file 
  393. * descriptor added by logFdAdd().  The file descriptor is not closed; but is
  394. * no longer used by the logging facilities.
  395. *
  396. * RETURNS:
  397. * OK, or ERROR if the file descriptor was not added with logFdAdd().
  398. *
  399. * SEE ALSO: logFdAdd()
  400. */
  401. STATUS logFdDelete
  402.     (
  403.     int fd      /* file descriptor to stop using as logging device */
  404.     )
  405.     {
  406.     FAST int ix;
  407.     FAST int jx;
  408.     semTake (&logFdSem, WAIT_FOREVER);
  409.     for (ix = jx = 0; ix < numLogFds; ix++, jx++)
  410. {
  411. /* shift array of logFd's after deleting unwanted fd */
  412. if (((logFd [jx] = logFd [ix]) == fd) && ix == jx)
  413.     jx--;
  414. }
  415.     if (ix == jx)
  416. {
  417. semGive (&logFdSem);
  418. return (ERROR); /* didn't find specified fd */
  419. }
  420.     numLogFds--;
  421.     semGive (&logFdSem);
  422.     return (OK);
  423.     }
  424. /*******************************************************************************
  425. *
  426. * logTask - message-logging support task
  427. *
  428. * This routine prints the messages logged with logMsg().  It waits on a
  429. * message queue and prints the messages as they arrive on the file descriptor
  430. * specified by logInit() (or a subsequent call to logFdSet() or logFdAdd()).
  431. *
  432. * This task is spawned by logInit().
  433. *
  434. * RETURNS: N/A
  435. *
  436. * SEE ALSO: logMsg()
  437. */
  438. void logTask (void)
  439.     {
  440.     static int oldMsgsLost;
  441.     int newMsgsLost; /* used in case logMsgsLost is changed during use */
  442.     LOG_MSG msg;
  443.     char *checkName;
  444.     FOREVER
  445. {
  446. if (msgQReceive (logMsgQId, (char *) &msg, sizeof (msg),
  447.  WAIT_FOREVER) != sizeof (msg))
  448.     lprintf ("logTask: error reading log messages.n", 0, 0, 0, 0, 0,0);
  449. else
  450.     {
  451.     /* print task ID followed by caller's message */
  452.     /* print task ID */
  453.     if (msg.id == -1)
  454. {
  455. lprintf ("interrupt: ", 0, 0, 0, 0, 0, 0);
  456. }
  457.     else
  458. {
  459. if ((checkName = taskName (msg.id)) == NULL)
  460.     lprintf ("%#x (): task dead", msg.id, 0, 0, 0, 0, 0);
  461. else
  462.     lprintf ("%#x (%s): ", msg.id, (int)checkName, 0, 0, 0, 0);
  463. }
  464.     if (msg.fmt == NULL)
  465. lprintf ("<null "fmt" parameter>n", 0, 0, 0, 0, 0, 0);
  466.     else
  467. {
  468. lprintf (msg.fmt, msg.arg[0], msg.arg[1], msg.arg[2],
  469.   msg.arg[3], msg.arg[4], msg.arg[5]);
  470. }
  471.     }
  472. /* check for any more messages lost */
  473. newMsgsLost = logMsgsLost;
  474. if (newMsgsLost != oldMsgsLost)
  475.     {
  476.     lprintf ("logTask: %d log messages lost.n",
  477.      newMsgsLost - oldMsgsLost, 0, 0, 0, 0, 0);
  478.     oldMsgsLost = newMsgsLost;
  479.     }
  480. }
  481.     }
  482. /*******************************************************************************
  483. *
  484. * lprintf - log printf
  485. *
  486. * Performs an fdprintf on all logFds.
  487. */
  488. LOCAL void lprintf
  489.     (
  490.     char *fmt, /* format string for print */
  491.     int arg1, /* optional arguments to fmt */
  492.     int arg2,
  493.     int arg3,
  494.     int arg4,
  495.     int arg5,
  496.     int arg6 
  497.     )
  498.     {
  499.     FAST int ix;
  500.     semTake (&logFdSem, WAIT_FOREVER);
  501.     for (ix = 0; ix < numLogFds; ix++)
  502. fdprintf (logFd [ix], fmt, arg1, arg2, arg3, arg4, arg5, arg6);
  503.     semGive (&logFdSem);
  504.     }
  505. /*******************************************************************************
  506. *
  507. * logShow - show active logging fd's (debug only)
  508. *
  509. * NOMANUAL
  510. */
  511. void logShow (void)
  512.     {
  513.     FAST int ix;
  514.     printf ("%3s %3sn", "num", "fd");
  515.     printf ("%3s %3sn", "---", "--");
  516.     for (ix = 0; ix < numLogFds; ix++)
  517. printf ("%3d %3dn", ix, logFd [ix]);
  518.     /* XXX timeout, message size, ...
  519.     msgQShow (logMsgQId, 1);
  520.     */
  521.     }