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

VxWorks

开发平台:

C/C++

  1. /* sigLib.c - software signal facility library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01m,17jul00,jgn  merge DOT-4 pthreads code
  8. 01l,20apr00,hk   changed sysBErrVecNum to excBErrVecNum for SH.
  9. 01k,03mar00,zl   merged SH support into T2
  10. 01j,18aug98,tpr  added PowerPC EC 603 support.
  11. 02l,08may98,pr   added extra parameter in WV macro
  12. 02k,23jan98,pr   commented out some of the WindView code
  13. 02j,13dec97,pr   added ifdef WV_INSTRUMENTATION to the WindView code
  14. 02i,13nov96,dgp  doc: add PowerPC info to table
  15. 02h,11jun96,dbt  fixed spr 5789. Added brackets for errnoSet in function
  16.  sigtimedwait().
  17. 02g,25nov95,jdi  removed 29k stuff.
  18. 02f,02feb95,rhp  correct argument refs in signal() man page,
  19.                  and misc doc cleanup
  20. 02e,16jan95,rhp  add pointer to POSIX 1003.1b fns in library man page
  21. 01w,19oct93,cd   added R4000 to documentation.
  22. 01w,03feb94,hdn  fixed spr 2996. for-loop in sigExcKill() ends if both are 0.
  23.  added a comment for I80X86 support.
  24. 01w,20mar94,pme  Added Am29030 and Am29200 exception signals definitions.
  25. 02d,06jul94,rrr  added save/restore of resumption record for the I960KB.
  26. 02c,08apr94,dvs  added doc on signal handler definition (SPR #3222).
  27. 02b,07apr94,smb  changed parameter to EVENT_SIGSUSPEND
  28. 02a,24mar94,smb  fixed event collection for sigsuspend
  29. 01z,02feb94,kdl  fixed condition around ffsMsb() prototype; deleted sigwait()
  30.  from structure diagram.
  31. 01y,28jan94,kdl  added declaration of sigEvtRtn (from sigLibP.h); added include
  32.  of sysLib.h; added prototype for ffsMsb()..
  33. 01x,24jan94,smb  added instrumentation macros.
  34.  changed description for 01w.
  35. 01w,10dec93,smb  added instrumentation and POSIX phase 1 additions.
  36. 01v,16sep93,rrr  fixed spr 2226,2227
  37. 01u,01mar93,jdi  doc: additions to section on signal handlers.
  38. 01t,09feb93,rrr  fixed spelling in doc, removed sigstack() and sigreturn()
  39.  from table correlating bsd and posix interface.
  40. 01s,03feb93,rrr  fixed src 1903,1904,1905 which are not reseting the handler
  41.  and corrected the use of sa_mask
  42. 01r,03feb93,jdi  documentation cleanup for 5.1; augmented arch-specific
  43.  exception tables.
  44. 01q,13nov92,dnw  added include of smObjLib.h
  45. 01p,15oct92,rrr  Fixed alignment of stack for 960 and sparc (spr #1628)
  46. 01o,29sep92,rrr  NOMANUAL a bunch of routines. The function signal produces
  47.                  an error with mangen (but the output looks ok).
  48. 01n,31aug92,rrr  fixed the code passed from excLib to be the exception vector
  49. 01m,18aug92,rrr  bug fix for timers.
  50. 01l,31jul92,rrr  changed _sig_timeout_recalc to _func_sigTimeoutRecalc
  51. 01k,30jul92,rrr  undo of 01j (now back to 01i)
  52. 01j,30jul92,kdl  backed out 01i changes pending rest of exc handling.
  53. 01i,29jul92,rrr  added in hook for exceptions to call signals directly.
  54. 01h,28jul92,jcf  falsed out delete hook that was causing grief for shell scripts
  55. 01g,27jul92,rrr  a quick checkin to test timers, still more testing needed.
  56. 01f,23jul92,ajm  moved _sig_timeout_recalc to taskLib to shrink proms
  57. 01e,27jul92,rrr  added install of signals to excLib 
  58. 01d,19jul92,pme  changed sigWindRestart() to handle shared semaphore take.
  59.  added include stddef.h.
  60. 01c,18jul92,smb  Changed errno.h to errnoLib.h.
  61. 01b,10jul92,rrr  removed setjmp (now it is a macro in setjmp.h)
  62. 01a,31jan92,rrr  written.
  63. */
  64. /*
  65. DESCRIPTION
  66. This library provides a signal interface for tasks.  Signals are used to
  67. alter the flow control of tasks by communicating asynchronous events
  68. within or between task contexts.  Any task or interrupt service can
  69. "raise" (or send) a signal to a particular task.  The task being signaled
  70. will immediately suspend its current thread of execution and invoke a
  71. task-specified "signal handler" routine.  The signal handler is a
  72. user-supplied routine that is bound to a specific signal and performs
  73. whatever actions are necessary whenever the signal is received.  Signals
  74. are most appropriate for error and exception handling, rather than as a
  75. general purpose intertask communication mechanism.
  76. This library has both a BSD 4.3 and POSIX signal interface.  The POSIX
  77. interface provides a standardized interface which is more functional than
  78. the traditional BSD 4.3 interface.  The chart below shows the correlation
  79. between BSD 4.3 and POSIX 1003.1 functions.  An application should use only one
  80. form of interface and not intermix them.
  81. .TS
  82. tab(|);
  83. lf3 lf3
  84. l   l.
  85. .ne 4
  86. %BSD 4.3    | POSIX 1003.1
  87. _
  88. sigmask()    | sigemptyset(), sigfillset(), sigaddset(),
  89.      |    sigdelset(), sigismember()
  90. sigblock()   | sigprocmask()
  91. sigsetmask() | sigprocmask()
  92. pause()      | sigsuspend()
  93. sigvec()     | sigaction()
  94. (none)       | sigpending()
  95. signal()     | signal()
  96. kill()       | kill()
  97. .TE
  98. POSIX 1003.1b (Real-Time Extensions) also specifies a queued-signal
  99. facility that involves four additional routines: sigqueue(),
  100. sigwaitinfo(), and sigtimedwait().
  101. In many ways, signals are analogous to hardware interrupts.  The signal
  102. facility provides a set of 31 distinct signals.  A signal can be raised by
  103. calling kill(), which is analogous to an interrupt or hardware exception.
  104. A signal handler is bound to a particular signal with sigaction() in much
  105. the same way that an interrupt service routine is connected to an
  106. interrupt vector with intConnect().  Signals are blocked for the duration
  107. of the signal handler, just as interrupts are locked out for the duration
  108. of the interrupt service routine.  Tasks can block the occurrence of
  109. certain signals with sigprocmask(), just as the interrupt level can be
  110. raised or lowered to block out levels of interrupts.  If a signal is
  111. blocked when it is raised, its handler routine will be called when the
  112. signal becomes unblocked.
  113. Several routines (sigprocmask(), sigpending(), and sigsuspend()) take 
  114. `sigset_t' data structures as parameters.  These data structures are 
  115. used to specify signal set masks.  Several routines are provided for 
  116. manipulating these data structures: sigemptyset() clears all the bits 
  117. in a `segset_t',  sigfillset() sets all the bits in a `sigset_t', 
  118. sigaddset() sets the bit in a `sigset_t' corresponding to a particular 
  119. signal number, sigdelset() resets the bit in a `sigset_t' corresponding 
  120. to a particular signal number, and sigismember() tests to see if the 
  121. bit corresponding to a particular signal number is set.
  122. FUNCTION RESTARTING
  123. If a task is pended (for instance, by waiting for a semaphore to become
  124. available) and a signal is sent to the task for which the task has a
  125. handler installed, then the handler will run before the semaphore is
  126. taken.  When the handler is done, the task will go back to being pended
  127. (waiting for the semaphore).  If there was a timeout used for the pend,
  128. then the original value will be used again when the task returns from the
  129. signal handler and goes back to being pended.
  130. Signal handlers are typically defined as:
  131. .ne 7
  132. .CS
  133.     void sigHandler
  134.         (
  135. int sig, /@ signal number                 @/
  136.         )
  137. {
  138.             ...
  139.         }
  140. .CE
  141. In VxWorks, the signal handler is passed additional arguments and can be
  142. defined as:
  143. .ne 9
  144. .CS
  145.     void sigHandler
  146.         (
  147. int sig, /@ signal number                 @/
  148.         int code, /@ additional code               @/
  149.         struct sigcontext *pSigContext /@ context of task before signal @/
  150.         )
  151. {
  152.             ...
  153.         }
  154. .CE
  155. The parameter <code> is valid only for signals caused by hardware
  156. exceptions.  In this case, it is used to distinguish signal variants.
  157. For example, both numeric overflow and zero divide raise SIGFPE
  158. (floating-point exception) but have different values for <code>.
  159. (Note that when the above VxWorks extensions are used, the compiler
  160. may issue warnings.)
  161. SIGNAL HANDLER DEFINITION
  162. Signal handling routines must follow one of two specific formats, so that they
  163. may be correctly called by the operating system when a signal occurs.  
  164. Traditional signal handlers receive the signal number as the sole input 
  165. parameter.  However, certain signals generated by routines which make up the
  166. POSIX Real-Time Extensions (P1003.1b) support the passing of an additional
  167. application-specific value to the handler routine.  These include signals
  168. generated by the sigqueue() call, by asynchronous I/O, by POSIX real-time
  169. timers, and by POSIX message queues.
  170. If a signal handler routine is to receive these additional parameters,
  171. SA_SIGINFO must be set in the sa_flags field of the sigaction structure which
  172. is a parameter to the sigaction() routine.  Such routines must take the
  173. following form:
  174. .CS
  175. void sigHandler (int sigNum, siginfo_t * pInfo, void * pContext);
  176. .CE
  177. Traditional signal handling routines must not set SA_SIGINFO in the sa_flags
  178. field, and must take the form of:
  179. .CS
  180.         void sigHandler (int sigNum);
  181. .CE
  182. EXCEPTION PROCESSING:
  183. Certain signals, defined below, are raised automatically when
  184. hardware exceptions are encountered.  This mechanism allows user-defined
  185. exception handlers to be installed.  This is useful for recovering from
  186. catastrophic events such as bus or arithmetic errors.  Typically, setjmp()
  187. is called to define the point in the program where control will be
  188. restored, and longjmp() is called in the signal handler to restore that
  189. context.  Note that longjmp() restores the state of the task's signal
  190. mask.  If a user-defined handler is not installed or the installed handler
  191. returns for a signal raised by a hardware exception, then the task is
  192. suspended and a message is logged to the console.
  193. The following is a list of hardware exceptions caught by VxWorks and delivered
  194. to the offending task.  The user may include the higher-level header file
  195. sigCodes.h in order to access the appropriate architecture-specific header file
  196. containing the code value.
  197. .SS "Motorola 68K"
  198. .TS
  199. tab(|);
  200. lf3 lf3 lf3
  201. l1p8 l0p8 l.
  202. Signal  | Code               | Exception
  203. _
  204. SIGSEGV | NULL               | bus error
  205. SIGBUS  | BUS_ADDERR         | address error
  206. SIGILL  | ILL_ILLINSTR_FAULT | illegal instruction
  207. SIGFPE  | FPE_INTDIV_TRAP    | zero divide
  208. SIGFPE  | FPE_CHKINST_TRAP   | chk trap
  209. SIGFPE  | FPE_TRAPV_TRAP     | trapv trap
  210. SIGILL  | ILL_PRIVVIO_FAULT  | privilege violation
  211. SIGTRAP | NULL               | trace exception
  212. SIGEMT  | EMT_EMU1010        | line 1010 emulator
  213. SIGEMT  | EMT_EMU1111        | line 1111 emulator
  214. SIGILL  | ILL_ILLINSTR_FAULT | coprocessor protocol violation
  215. SIGFMT  | NULL               | format error
  216. SIGFPE  | FPE_FLTBSUN_TRAP   | compare unordered
  217. SIGFPE  | FPE_FLTINEX_TRAP   | inexact result
  218. SIGFPE  | FPE_FLTDIV_TRAP    | divide by zero
  219. SIGFPE  | FPE_FLTUND_TRAP    | underflow
  220. SIGFPE  | FPE_FLTOPERR_TRAP  | operand error
  221. SIGFPE  | FPE_FLTOVF_TRAP    | overflow
  222. SIGFPE  | FPE_FLTNAN_TRAP    | signaling "Not A Number"
  223. .TE
  224. .SS "SPARC"
  225. .TS
  226. tab(|);
  227. lf3 lf3 lf3
  228. l1p8 l0p8 l.
  229. Signal | Code                | Exception
  230. _
  231. SIGBUS | BUS_INSTR_ACCESS    | bus error on instruction fetch
  232. SIGBUS | BUS_ALIGN           | address error (bad alignment)
  233. SIGBUS | BUS_DATA_ACCESS     | bus error on data access
  234. SIGILL | ILL_ILLINSTR_FAULT  | illegal instruction
  235. SIGILL | ILL_PRIVINSTR_FAULT | privilege violation
  236. SIGILL | ILL_COPROC_DISABLED | coprocessor disabled
  237. SIGILL | ILL_COPROC_EXCPTN   | coprocessor exception
  238. SIGILL | ILL_TRAP_FAULT(n)   | uninitialized user trap
  239. SIGFPE | FPE_FPA_ENABLE      | floating point disabled
  240. SIGFPE | FPE_FPA_ERROR       | floating point exception
  241. SIGFPE | FPE_INTDIV_TRAP     | zero divide
  242. SIGEMT | EMT_TAG             | tag overflow
  243. .TE
  244. .SS "Intel i960"
  245. .TS
  246. tab(|);
  247. lf3 lf3 lf3
  248. l1p8 l0p8 l.
  249. Signal  | Code                           | Exception
  250. _
  251. SIGBUS  | BUS_UNALIGNED                  | address error (bad alignment)
  252. SIGBUS  | BUS_BUSERR                     | bus error
  253. SIGILL  | ILL_INVALID_OPCODE             | invalid instruction
  254. SIGILL  | ILL_UNIMPLEMENTED              | instr fetched from on-chip RAM
  255. SIGILL  | ILL_INVALID_OPERAND            | invalid operand
  256. SIGILL  | ILL_CONSTRAINT_RANGE           | constraint range failure
  257. SIGILL  | ILL_PRIVILEGED                 | privilege violation
  258. SIGILL  | ILL_LENGTH                     | bad index to sys procedure table
  259. SIGILL  | ILL_TYPE_MISMATCH              | privilege violation
  260. SIGTRAP | TRAP_INSTRUCTION_TRACE         | instruction trace fault
  261. SIGTRAP | TRAP_BRANCH_TRACE              | branch trace fault
  262. SIGTRAP | TRAP_CALL_TRACE                | call trace fault
  263. SIGTRAP | TRAP_RETURN_TRACE              | return trace fault
  264. SIGTRAP | TRAP_PRERETURN_TRACE           | pre-return trace fault
  265. SIGTRAP | TRAP_SUPERVISOR_TRACE          | supervisor trace fault
  266. SIGTRAP | TRAP_BREAKPOINT_TRACE          | breakpoint trace fault
  267. SIGFPE  | FPE_INTEGER_OVERFLOW           | integer overflow
  268. SIGFPE  | FST_ZERO_DIVIDE                | integer zero divide
  269. SIGFPE  | FPE_FLOATING_OVERFLOW          | floating point overflow
  270. SIGFPE  | FPE_FLOATING_UNDERFLOW         | floating point underflow
  271. SIGFPE  | FPE_FLOATING_INVALID_OPERATION | invalid floating point operation
  272. SIGFPE  | FPE_FLOATING_ZERO_DIVIDE       | floating point zero divide
  273. SIGFPE  | FPE_FLOATING_INEXACT           | floating point inexact
  274. SIGFPE  | FPE_FLOATING_RESERVED_ENCODING | floating point reserved encoding
  275. .TE
  276. .SS "MIPS R3000/R4000"
  277. .TS
  278. tab(|);
  279. lf3 lf3 lf3
  280. l1p8 l0p8 l.
  281. Signal  | Code | Exception
  282. _
  283. SIGBUS  | BUS_TLBMOD          | TLB modified
  284. SIGBUS  | BUS_TLBL            | TLB miss on a load instruction
  285. SIGBUS  | BUS_TLBS            | TLB miss on a store instruction
  286. SIGBUS  | BUS_ADEL            | address error (bad alignment) on load instr
  287. SIGBUS  | BUS_ADES            | address error (bad alignment) on store instr
  288. SIGSEGV | SEGV_IBUS           | bus error (instruction)
  289. SIGSEGV | SEGV_DBUS           | bus error (data)
  290. SIGTRAP | TRAP_SYSCALL        | syscall instruction executed
  291. SIGTRAP | TRAP_BP             | break instruction executed
  292. SIGILL  | ILL_ILLINSTR_FAULT  | reserved instruction
  293. SIGILL  | ILL_COPROC_UNUSABLE | coprocessor unusable
  294. SIGFPE  | FPE_FPA_UIO, SIGFPE | unimplemented FPA operation
  295. SIGFPE  | FPE_FLTNAN_TRAP     | invalid FPA operation
  296. SIGFPE  | FPE_FLTDIV_TRAP     | FPA divide by zero
  297. SIGFPE  | FPE_FLTOVF_TRAP     | FPA overflow exception
  298. SIGFPE  | FPE_FLTUND_TRAP     | FPA underflow exception
  299. SIGFPE  | FPE_FLTINEX_TRAP    | FPA inexact operation
  300. .TE
  301. .SS "Intel i386/i486"
  302. .TS
  303. tab(|);
  304. lf3 lf3 lf3
  305. l1p8 l0p8 l.
  306. Signal  | Code                 | Exception
  307. _
  308. SIGILL  | ILL_DIVIDE_ERROR     | divide error
  309. SIGEMT  | EMT_DEBUG            | debugger call
  310. SIGILL  | ILL_NON_MASKABLE     | NMI interrupt
  311. SIGEMT  | EMT_BREAKPOINT       | breakpoint
  312. SIGILL  | ILL_OVERFLOW         | INTO-detected overflow
  313. SIGILL  | ILL_BOUND            | bound range exceeded
  314. SIGILL  | ILL_INVALID_OPCODE   | invalid opcode
  315. SIGFPE  | FPE_NO_DEVICE        | device not available
  316. SIGILL  | ILL_DOUBLE_FAULT     | double fault
  317. SIGFPE  | FPE_CP_OVERRUN       | coprocessor segment overrun
  318. SIGILL  | ILL_INVALID_TSS      | invalid task state segment
  319. SIGBUS  | BUS_NO_SEGMENT       | segment not present
  320. SIGBUS  | BUS_STACK_FAULT      | stack exception
  321. SIGILL  | ILL_PROTECTION_FAULT | general protection
  322. SIGBUS  | BUS_PAGE_FAULT       | page fault
  323. SIGILL  | ILL_RESERVED         | (intel reserved)
  324. SIGFPE  | FPE_CP_ERROR         | coprocessor error
  325. SIGBUS  | BUS_ALIGNMENT        | alignment check
  326. .TE
  327. .SS "PowerPC"
  328. .TS
  329. tab(|);
  330. lf3 lf3 lf3
  331. l1p8 l0p8 l.
  332. Signal  | Code                 | Exception
  333. _
  334. SIGBUS  | _EXC_OFF_MACH        | machine check
  335. SIGBUS  | _EXC_OFF_INST        | instruction access
  336. SIGBUS  | _EXC_OFF_ALIGN       | alignment
  337. SIGILL  | _EXC_OFF_PROG        | program
  338. SIGBUS  | _EXC_OFF_DATA        | data access
  339. SIGFPE  | _EXC_OFF_FPU         | floating point unavailable
  340. SIGTRAP | _EXC_OFF_DBG         | debug exception (PPC403)
  341. SIGTRAP | _EXC_OFF_INST_BRK    | inst. breakpoint (PPC603, PPCEC603, PPC604)
  342. SIGTRAP | _EXC_OFF_TRACE       | trace (PPC603, PPCEC603, PPC604, PPC860)
  343. SIGBUS  | _EXC_OFF_CRTL        | critical interrupt (PPC403)
  344. SIGILL  | _EXC_OFF_SYSCALL     | system call
  345. .TE
  346. .SS "Hitachi SH770x"
  347. .TS
  348. tab(|);
  349. lf3 lf3 lf3
  350. l1p8 l0p8 l.
  351. Signal  | Code                       | Exception
  352. _
  353. SIGSEGV | TLB_LOAD_MISS              | TLB miss/invalid (load)
  354. SIGSEGV | TLB_STORE_MISS             | TLB miss/invalid (store)
  355. SIGSEGV | TLB_INITITIAL_PAGE_WRITE   | Initial page write
  356. SIGSEGV | TLB_LOAD_PROTEC_VIOLATION  | TLB protection violation (load)
  357. SIGSEGV | TLB_STORE_PROTEC_VIOLATION | TLB protection violation (store)
  358. SIGBUS  | BUS_LOAD_ADDRESS_ERROR     | Address error (load)
  359. SIGBUS  | BUS_STORE_ADDRESS_ERROR    | Address error (store)
  360. SIGILL  | ILLEGAL_INSTR_GENERAL      | general illegal instruction
  361. SIGILL  | ILLEGAL_SLOT_INSTR         | slot illegal instruction
  362. SIGFPE  | FPE_INTDIV_TRAP            | integer zero divide
  363. .TE
  364. .SS "Hitachi SH7604/SH704x/SH703x/SH702x"
  365. .TS
  366. tab(|);
  367. lf3 lf3 lf3
  368. l1p8 l0p8 l.
  369. Signal | Code                 | Exception
  370. _
  371. SIGILL | ILL_ILLINSTR_GENERAL | general illegal instruction
  372. SIGILL | ILL_ILLINSTR_SLOT    | slot illegal instruction
  373. SIGBUS | BUS_ADDERR_CPU       | CPU address error
  374. SIGBUS | BUS_ADDERR_DMA       | DMA address error
  375. SIGFPE | FPE_INTDIV_TRAP      | integer zero divide
  376. .TE
  377. Two signals are provided for application use: SIGUSR1 and SIGUSR2.  
  378. VxWorks will never use these signals; however, other signals may be used by
  379. VxWorks in the future.
  380. INTERNAL:
  381. WINDVIEW INSTRUMENTATION
  382. Level 1:
  383.         signal() causes EVENT_SIGNAL
  384.         sigsuspend() causes EVENT_SIGSUSPEND
  385.         pause() causes EVENT_PAUSE
  386.         kill() causes EVENT_KILL
  387.         sigWrapper() causes EVENT_SIGWRAPPER
  388. Level 2:
  389.         sigsuspend() causes EVENT_OBJ_SIGSUSPEND
  390.         pause() causes EVENT_OBJ_SIGPAUSE
  391.         sigtimedwait() causes EVENT_OBJ_SIGWAIT
  392.         sigWindPendKill() causes EVENT_OBJ_SIGKILL
  393. Level 3:
  394.         N/A
  395. INTERNAL:
  396.   raise                           sigreturn                         sigwaitinfo
  397.     |                                                                /
  398.   kill         sigPendKill            sigprocmask  sigsuspend  sigtimedwait
  399.     |               |                       _________/            |
  400. sigWindKill         |                            |                 |
  401.     |               |                            |                 |
  402.      _____   _____/                             |                 |
  403.             /                              sigPendRun             |
  404.       sigWindPendKill                            |                 |
  405.             |                                    |_______   _____/
  406.             |__________________________________ |         /
  407.             |    (->if I sent myself a sig ->)  |     sigPendGet
  408.             |                                    |
  409.             |                                    |
  410.             |_sigWindRestart                    |
  411.             |__sigCtxStackEnd                   |
  412.              __sigCtxSetup         _sigCtxSave_/
  413.                      
  414.                   _________________________________________
  415.                   |                                       |
  416.                   |        ----------->sigWrapper         |
  417.                   |                        |              |
  418.                   |                    sigreturn          |
  419.                   |_______________________________________|
  420.                    ran in context of task receiving signal
  421. The function sigstack is not, and will not be implemented.
  422. All other functions below are done.
  423. BSD 4.3 POSIX
  424. ------- -----
  425. sigmask sigemptyset sigfillset sigaddset sigdelset sigismember
  426. sigblock sigprocmask
  427. sigsetmask sigprocmask
  428. pause sigsuspend
  429. sigvec sigaction
  430. sigstack (none)
  431. sigreturn (none)
  432. (none) sigpending
  433. signal signal
  434. The only major difference between this and posix is that the default action
  435. when a signal occurs in vxWorks is to ignore it and in Posix is to kill the
  436. process.
  437. INCLUDE FILES: signal.h
  438. SEE ALSO: intLib, IEEE 
  439. .I "POSIX 1003.1b,"
  440. .pG "Basic OS"
  441. */
  442. #include "vxWorks.h"
  443. #include "private/sigLibP.h"
  444. #include "private/windLibP.h"
  445. #include "private/taskLibP.h"
  446. #include "private/kernelLibP.h"
  447. #include "private/funcBindP.h"
  448. #include "taskHookLib.h"
  449. #include "errnoLib.h"
  450. #include "intLib.h"
  451. #include "qFifoGLib.h"
  452. #include "stddef.h"
  453. #include "stdlib.h"
  454. #include "string.h"
  455. #include "excLib.h"
  456. #include "smObjLib.h"
  457. #include "taskArchLib.h"
  458. #include "timers.h"
  459. #include "private/eventP.h"
  460. #include "sysLib.h"
  461. #define __PTHREAD_SRC
  462. #include "pthread.h"
  463. /*
  464.  * Given a structure type, a member, and a pointer to that member, find the
  465.  * pointer to the structure.
  466.  */
  467. #define structbase(s,m,p)         ((s *)((char *)(p) - offsetof(s,m)))
  468. #define issig(m) (1 <= (m) && (m) <= _NSIGS)
  469. struct sigwait
  470.     {
  471.     sigset_t sigw_set;
  472.     struct siginfo sigw_info;
  473.     Q_HEAD sigw_wait;
  474.     };
  475. #if CPU_FAMILY != I960
  476. extern int ffsMsb (unsigned long);      /* not in any header */
  477. #endif
  478. /* global variables */
  479. #ifdef WV_INSTRUMENTATION
  480. VOIDFUNCPTR     sigEvtRtn; /* windview - level 1 event logging */
  481. #endif
  482. /* static variables */
  483. struct sigpend *_pSigQueueFreeHead;
  484. /* forward static functions */
  485. static void sigWindPendKill (WIND_TCB *, struct sigpend *);
  486. static struct sigtcb *sigTcbGet (void);
  487. static void sigWindKill (WIND_TCB *pTcb, int signo);
  488. static int sigWindRestart (WIND_TCB *pTcb);
  489. static int sigTimeoutRecalc(int i);
  490. static void sigDeleteHook (WIND_TCB *pNewTcb);
  491. static void sigWrapper (struct sigcontext *pContext);
  492. static int sigPendRun (struct sigtcb *pSigTcb);
  493. static int sigPendGet (struct sigtcb *pSigTcb,
  494.     const sigset_t *sigset,
  495.     struct siginfo *info);
  496. static void sigExcKill (int faultType, int faultSubtype,
  497.     REG_SET *pRegSet);
  498. /*******************************************************************************
  499. *
  500. * sigInit - initialize the signal facilities
  501. *
  502. * This routine initializes the signal facilities.  It is usually called from
  503. * the system start-up routine usrInit() in usrConfig, before interrupts are
  504. * enabled.
  505. *
  506. * RETURNS: OK, or ERROR if the delete hooks cannot be installed.
  507. *
  508. * ERRNO: S_taskLib_TASK_HOOK_TABLE_FULL
  509. */
  510. int sigInit (void)
  511.     {
  512.     static BOOL sigInstalled = FALSE;
  513.     if (!sigInstalled)
  514.         {
  515.         _func_sigTimeoutRecalc = sigTimeoutRecalc;
  516. _func_sigExcKill = sigExcKill;
  517. _func_sigprocmask = sigprocmask;
  518.         if (taskDeleteHookAdd ((FUNCPTR) sigDeleteHook) == ERROR)
  519.             return (ERROR);
  520. /* FIXME-PR I do not think sigEvtRtn should be initialized here 
  521.  * It is also initialize in wvLib.c and that should be enough 
  522.  */
  523. #if 0 
  524. #ifdef WV_INSTRUMENTATION
  525.         /* windview instrumentation - level 1 */
  526.         if (WV_EVTCLASS_IS_SET(WV_CLASS_3))                  /* connect event logging routine */
  527.             sigEvtRtn = _func_evtLogOIntLock;
  528.         else
  529.             sigEvtRtn = NULL;           /* disconnect event logging */
  530. #endif
  531. #endif
  532.         sigInstalled = TRUE;
  533.         }
  534.  
  535.     return (OK);
  536.     }
  537. /*******************************************************************************
  538. *
  539. * sigqueueInit - initialize the queued signal facilities
  540. *
  541. * This routine initializes the queued signal facilities. It must
  542. * be called before any call to sigqueue().  It is usually
  543. * called from the system start-up routine usrInit() in usrConfig,
  544. * after sysInit() is called.
  545. *
  546. * It allocates <nQueues> buffers to be used by sigqueue(). A buffer is
  547. * used by each call to sigqueue() and freed when the signal is delivered
  548. * (thus if a signal is block, the buffer is unavailable until the signal
  549. * is unblocked.)
  550. *
  551. * RETURNS: OK, or ERROR if memory could not be allocated.
  552. */
  553. int sigqueueInit
  554.     (
  555.     int nQueues
  556.     )
  557.     {
  558.     static BOOL sigqueueInstalled = FALSE;
  559.     struct sigpend *p;
  560.     if (!sigqueueInstalled)
  561.         {
  562. if (nQueues < 1)
  563.     return (ERROR);
  564. if ((p = (struct sigpend *)malloc(nQueues * sizeof(struct sigpend)))
  565.     == NULL)
  566.     return (ERROR);
  567. while (nQueues-- > 0)
  568.     {
  569.     *(struct sigpend **)p= _pSigQueueFreeHead;
  570.     _pSigQueueFreeHead = p;
  571.     p++;
  572.     }
  573.         sigqueueInstalled = TRUE;
  574.         }
  575.  
  576.     return (OK);
  577.     }
  578. /*******************************************************************************
  579. *
  580. * sigDeleteHook - task delete hook for signal facility
  581. *
  582. * Cleanup any signals a task has hanging on it before the task gets
  583. * deleted.
  584. *
  585. * RETURNS: Nothing.
  586. */
  587. static void sigDeleteHook
  588.     (
  589.     WIND_TCB *pTcb /* pointer to old task's TCB */
  590.     )
  591.     {
  592.     struct sigtcb *pSigTcb = pTcb->pSignalInfo;
  593.     struct sigpend *pSigPend;
  594.     struct sigq *pSigQ;
  595.     int ix;
  596.     /*
  597.      * If I never got any signals, nothing to clean up
  598.      */
  599.     if (pSigTcb == NULL)
  600. return;
  601.     kernelState = TRUE; /* KERNEL ENTER */
  602.     for (ix = 0; ix <= _NSIGS; ix++)
  603. {
  604. pSigQ = pSigTcb->sigt_qhead[ix].sigq_next;
  605. while (pSigQ != &pSigTcb->sigt_qhead[ix])
  606.     {
  607.     pSigPend = structbase(struct sigpend, sigp_q, pSigQ);
  608.     pSigQ = pSigQ->sigq_next;
  609.     pSigPend->sigp_q.sigq_next = pSigPend->sigp_q.sigq_prev = NULL;
  610.     /*
  611.      * free queued signal buffer
  612.      */
  613.     if (pSigPend->sigp_info.si_code == SI_QUEUE)
  614. {
  615. *(struct sigpend **)pSigPend = _pSigQueueFreeHead;
  616. _pSigQueueFreeHead = pSigPend;
  617. }
  618.     }
  619. }
  620.     windExit (); /* KERNEL EXIT */
  621.     }
  622. /*******************************************************************************
  623. *
  624. * sigTimeoutRecalc - Compute the new timeout when a function restarts
  625. *
  626. * Compute the new timeout when a function restarts.  For example, a
  627. * task pends on a semTake() with a timeout, receives a signal, runs the signal
  628. * handler, and then goes back to waiting on the semTake().  What timeout
  629. * should it use when it blocks?  In this example, it uses the original
  630. * timeout passed to semTake().
  631. *
  632. * RETURNS: The new timeout value.
  633. */
  634. static int sigTimeoutRecalc
  635.     (
  636.     int timeout /* original timeout value */
  637.     )
  638.     {
  639.     return (timeout);
  640.     }
  641. /*******************************************************************************
  642. *
  643. * sigemptyset - initialize a signal set with no signals included (POSIX)
  644. *
  645. * This routine initializes the signal set specified by <pSet>, 
  646. * such that all signals are excluded.
  647. *
  648. * RETURNS: OK (0), or ERROR (-1) if the signal set cannot be initialized.
  649. *
  650. * ERRNO: No errors are detectable.
  651. */
  652. int sigemptyset
  653.     (
  654.     sigset_t *pSet /* signal set to initialize */
  655.     )
  656.     {
  657.     *pSet = 0;
  658.     return (OK);
  659.     }
  660. /*******************************************************************************
  661. *
  662. * sigfillset - initialize a signal set with all signals included (POSIX)
  663. *
  664. * This routine initializes the signal set specified by <pSet>, such that
  665. * all signals are included.
  666. *
  667. * RETURNS: OK (0), or ERROR (-1) if the signal set cannot be initialized.
  668. *
  669. * ERRNO: No errors are detectable.
  670. */
  671. int sigfillset
  672.     (
  673.     sigset_t *pSet /* signal set to initialize */
  674.     )
  675.     {
  676.     *pSet = 0xffffffff;
  677.     return (OK);
  678.     }
  679. /*******************************************************************************
  680. *
  681. * sigaddset - add a signal to a signal set (POSIX)
  682. *
  683. * This routine adds the signal specified by <signo> to the signal set 
  684. * specified by <pSet>.
  685. *
  686. * RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.
  687. *
  688. * ERRNO: EINVAL
  689. */
  690. int sigaddset
  691.     (
  692.     sigset_t *pSet, /* signal set to add signal to */
  693.     int signo /* signal to add */
  694.     )
  695.     {
  696.     if (issig (signo))
  697. {
  698. *pSet |= sigmask (signo);
  699. return (OK);
  700. }
  701.     errnoSet (EINVAL);
  702.     return (ERROR);
  703.     }
  704. /*******************************************************************************
  705. *
  706. * sigdelset - delete a signal from a signal set (POSIX)
  707. *
  708. * This routine deletes the signal specified by <signo> from the signal set
  709. * specified by <pSet>.
  710. *
  711. * RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.
  712. *
  713. * ERRNO: EINVAL
  714. */
  715. int sigdelset
  716.     (
  717.     sigset_t *pSet, /* signal set to delete signal from */
  718.     int signo /* signal to delete */
  719.     )
  720.     {
  721.     if (issig (signo))
  722. {
  723. *pSet &= ~sigmask (signo);
  724. return (OK);
  725. }
  726.     errnoSet (EINVAL);
  727.     return (ERROR);
  728.     }
  729. /*******************************************************************************
  730. *
  731. * sigismember - test to see if a signal is in a signal set (POSIX)
  732. *
  733. * This routine tests whether the signal specified by <signo> is
  734. * a member of the set specified by <pSet>.
  735. *
  736. * RETURNS: 1 if the specified signal is a member of the specified set, OK
  737. * (0) if it is not, or ERROR (-1) if the test fails.
  738. * ERRNO: EINVAL
  739. */
  740. int sigismember
  741.     (
  742.     const sigset_t      *pSet,  /* signal set to test */
  743.     int                 signo   /* signal to test for */
  744.     )
  745.     {
  746.     if (issig (signo))
  747.         return ((*pSet & sigmask (signo)) != 0);
  748.     errnoSet (EINVAL);
  749.     return (ERROR);
  750.     }
  751. /*******************************************************************************
  752. *
  753. * signal - specify the handler associated with a signal
  754. *
  755. * This routine chooses one of three ways in which receipt of the signal
  756. * number <signo> is to be subsequently handled.  If the value of <pHandler> is
  757. * SIG_DFL, default handling for that signal will occur.  If the value of
  758. * <pHandler> is SIG_IGN, the signal will be ignored.  Otherwise, <pHandler>
  759. * must point to a function to be called when that signal occurs.
  760. *
  761. * RETURNS: The value of the previous signal handler, or SIG_ERR.
  762. */
  763. void (*signal
  764.     (
  765.     int signo,
  766.     void (*pHandler) ()
  767.     )) ()
  768.     {
  769.     struct sigaction in, out;
  770.     in.sa_handler = pHandler;
  771.     in.sa_flags = 0;
  772.     (void) sigemptyset (&in.sa_mask);
  773.     return ((sigaction (signo, &in, &out) == ERROR) ? SIG_ERR : out.sa_handler);
  774.     }
  775. /*******************************************************************************
  776. *
  777. * sigaction - examine and/or specify the action associated with a signal (POSIX)
  778. *
  779. * This routine allows the calling process to examine and/or specify
  780. * the action to be associated with a specific signal.
  781. *
  782. * RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.
  783. *
  784. * ERRNO: EINVAL
  785. */
  786. int sigaction
  787.     (
  788.     int signo, /* signal of handler of interest */
  789.     const struct sigaction *pAct, /* location of new handler */
  790.     struct sigaction *pOact /* location to store old handler */
  791.     )
  792.     {
  793.     struct sigtcb *pSigTcb;
  794.     struct sigaction *pSigAction;
  795.     struct sigpend *pSigPend;
  796.     struct sigq *pSigQ;
  797.     if (!issig (signo))
  798. {
  799. errnoSet (EINVAL);
  800. return (ERROR);
  801. }
  802.     if ((pSigTcb = sigTcbGet ()) == NULL)
  803. return (ERROR); /* errno was set */
  804. #ifdef WV_INSTRUMENTATION
  805.     /* windview - level 1 event logging */
  806.     EVT_OBJ_SIG (EVENT_SIGNAL, 2, signo, ((int) pAct->sa_handler));
  807. #endif
  808.     pSigAction = &pSigTcb->sigt_vec[signo];
  809.     if (pOact != NULL)
  810. *pOact = *pSigAction;
  811.     if (pAct != NULL)
  812. {
  813. kernelState = TRUE; /* KERNEL ENTER */
  814. *pSigAction = *pAct;
  815. /*
  816.  * if the new action is to ignore, then any pending
  817.  * signals must be removed.
  818.  */
  819. if (pSigAction->sa_handler == SIG_IGN)
  820.     {
  821.     sigdelset (&pSigTcb->sigt_pending, signo);
  822.     sigdelset (&pSigTcb->sigt_kilsigs, signo);
  823. /* XXX need to destroy queued signals */
  824.     pSigQ = pSigTcb->sigt_qhead[signo].sigq_next;
  825.     while (pSigQ != &pSigTcb->sigt_qhead[signo])
  826. {
  827. pSigPend = structbase(struct sigpend, sigp_q, pSigQ);
  828. pSigQ = pSigQ->sigq_next;
  829. pSigPend->sigp_q.sigq_next = pSigPend->sigp_q.sigq_prev = NULL;
  830. /*
  831.  * free queued signal buffer
  832.  */
  833. if (pSigPend->sigp_info.si_code == SI_QUEUE)
  834.     {
  835.     *(struct sigpend **)pSigPend = _pSigQueueFreeHead;
  836.     _pSigQueueFreeHead = pSigPend;
  837.     }
  838. }
  839.     }
  840. windExit (); /* KERNEL EXIT */
  841. }
  842.     return (OK);
  843.     }
  844. /*******************************************************************************
  845. *
  846. * sigprocmask - examine and/or change the signal mask (POSIX)
  847. *
  848. * This routine allows the calling process to examine and/or change its
  849. * signal mask.  If the value of <pSet> is not NULL, it points to a set of
  850. * signals to be used to change the currently blocked set.
  851. *
  852. * The value of <how> indicates the manner in which the set is changed and
  853. * consists of one of the following, defined in signal.h:
  854. * .iP SIG_BLOCK 4
  855. * the resulting set is the union of the current set and the signal set
  856. * pointed to by <pSet>.
  857. * .iP SIG_UNBLOCK
  858. * the resulting set is the intersection of the current set and the complement
  859. * of the signal set pointed to by <pSet>.
  860. * .iP SIG_SETMASK
  861. * the resulting set is the signal set pointed to by <pSset>.
  862. *
  863. * RETURNS: OK (0), or ERROR (-1) if <how> is invalid.
  864. *
  865. * ERRNO: EINVAL
  866. *
  867. * SEE ALSO: sigsetmask(), sigblock()
  868. */
  869. int sigprocmask
  870.     (
  871.     int how, /* how signal mask will be changed */
  872.     const sigset_t *pSet, /* location of new signal mask */
  873.     sigset_t *pOset /* location to store old signal mask */
  874.     )
  875.     {
  876.     struct sigtcb *pSigTcb;
  877.     if ((pSigTcb = sigTcbGet()) == NULL)
  878. return (ERROR); /* errno was set */
  879.     kernelState = TRUE; /* KERNEL ENTER */
  880.     if (pOset != NULL)
  881. *pOset = pSigTcb->sigt_blocked;
  882.     if (pSet != NULL)
  883. switch (how)
  884.     {
  885.     case SIG_BLOCK:
  886. pSigTcb->sigt_blocked |= *pSet;
  887. windExit (); /* KERNEL EXIT */
  888. return (OK);
  889.     case SIG_UNBLOCK:
  890. pSigTcb->sigt_blocked &= ~*pSet;
  891. break;
  892.     case SIG_SETMASK:
  893. pSigTcb->sigt_blocked = *pSet;
  894. break;
  895.     default:
  896. windExit (); /* KERNEL EXIT */
  897. errnoSet (EINVAL);
  898. return (ERROR);
  899.     }
  900.     /*
  901.      * check to see if we opened up any pending signals and run them.
  902.      * sigpendrun has the horrible symantic of doing a windExit if
  903.      * successful.
  904.      */
  905.     if (sigPendRun(pSigTcb) == FALSE)
  906. windExit (); /* KERNEL EXIT */
  907.     return (OK);
  908.     }
  909. /*******************************************************************************
  910. *
  911. * sigpending - retrieve the set of pending signals blocked from delivery (POSIX)
  912. *
  913. * This routine stores the set of signals that are blocked from delivery and
  914. * that are pending for the calling process in the space pointed to by
  915. * <pSet>.
  916. *
  917. * RETURNS: OK (0), or ERROR (-1) if the signal TCB cannot
  918. * be allocated.
  919. *
  920. * ERRNO: ENOMEM
  921. */
  922. int sigpending
  923.     (
  924.     sigset_t *pSet /* location to store pending signal set */
  925.     )
  926.     {
  927.     struct sigtcb *pSigTcb;
  928.     if ((pSigTcb = sigTcbGet ()) == NULL)
  929. return (ERROR);
  930.     *pSet = pSigTcb->sigt_pending;
  931.     return (OK);
  932.     }
  933. /*******************************************************************************
  934. *
  935. * sigsuspend - suspend the task until delivery of a signal (POSIX)
  936. *
  937. * This routine suspends the task until delivery of a signal.  While
  938. * suspended, <pSet> is used as the set of masked signals.
  939. *
  940. * NOTE: Since the sigsuspend() function suspends thread execution
  941. * indefinitely, there is no successful completion return value.
  942. *
  943. * RETURNS: -1, always.
  944. *
  945. * ERRNO: EINTR
  946. */
  947. int sigsuspend
  948.     (
  949.     const sigset_t *pSet /* signal mask while suspended */
  950.     )
  951.     {
  952.     Q_HEAD qHead;
  953.     sigset_t oldset;
  954.     struct sigtcb *pSigTcb;
  955.     int savtype;
  956.     if ((pSigTcb = sigTcbGet ()) == NULL)
  957.         return (ERROR); /* errno was set */
  958. #ifdef WV_INSTRUMENTATION
  959.     /* windview - level 1 event logging */
  960.     EVT_OBJ_SIG (EVENT_SIGSUSPEND, 1, (int) *pSet, 0);
  961. #endif
  962.     if (_func_pthread_setcanceltype != NULL)
  963.         {
  964.         _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);
  965.         }
  966.     kernelState = TRUE; /* KERNEL ENTER */
  967.     /* save old set */
  968.     oldset = pSigTcb->sigt_blocked;
  969.     pSigTcb->sigt_blocked = *pSet;
  970.     /* check for pending */
  971.     if (sigPendRun (pSigTcb) == TRUE)
  972. {
  973. sigprocmask (SIG_SETMASK, &oldset, NULL);
  974. if (_func_pthread_setcanceltype != NULL)
  975.             {
  976.             _func_pthread_setcanceltype(savtype, NULL);
  977.             }
  978. errnoSet (EINTR);
  979. return (ERROR);
  980. }
  981.     /*
  982.      * Put ourself to sleep until a signal comes in.
  983.      */
  984.     qInit (&qHead, Q_FIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  985. #ifdef WV_INSTRUMENTATION
  986.     /* windview - level 2 event logging */
  987.     EVT_TASK_1 (EVENT_OBJ_SIGSUSPEND, pSet); 
  988. #endif
  989.     if (windPendQPut (&qHead, WAIT_FOREVER) != OK)
  990.         {
  991. windExit (); /* KERNEL EXIT */
  992.         if (_func_pthread_setcanceltype != NULL)
  993.             {
  994.             _func_pthread_setcanceltype(savtype, NULL);
  995.             }
  996. return (ERROR);
  997.         }
  998.     windExit (); /* KERNEL EXIT */
  999.     /*
  1000.      * Restore old mask set.
  1001.      */
  1002.     sigprocmask(SIG_SETMASK, &oldset, NULL);
  1003.     if (_func_pthread_setcanceltype != NULL)
  1004.         {
  1005.         _func_pthread_setcanceltype(savtype, NULL);
  1006.         }
  1007.     errnoSet (EINTR);
  1008.     return (ERROR);
  1009.     }
  1010. /*******************************************************************************
  1011. *
  1012. * pause - suspend the task until delivery of a signal (POSIX)
  1013. *
  1014. * This routine suspends the task until delivery of a signal.
  1015. *
  1016. * NOTE: Since the pause() function suspends thread execution indefinitely,
  1017. * there is no successful completion return value.
  1018. *
  1019. * RETURNS: -1, always.
  1020. *
  1021. * ERRNO: EINTR
  1022. */
  1023. int pause (void)
  1024.     {
  1025.     Q_HEAD qHead;
  1026.     int savtype;
  1027. #ifdef WV_INSTRUMENTATION
  1028.     /* windview - level 1 event logging */
  1029.     EVT_OBJ_SIG (EVENT_PAUSE, 1, taskIdCurrent,0);
  1030. #endif
  1031.     if (_func_pthread_setcanceltype != NULL)
  1032.         {
  1033.         _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);
  1034.         }
  1035.     /*
  1036.      * Put ourself to sleep until a signal comes in.
  1037.      */
  1038.     qInit (&qHead, Q_FIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  1039.     kernelState = TRUE; /* KERNEL ENTER */
  1040. #ifdef WV_INSTRUMENTATION
  1041.     /* windview - level 2 event logging */
  1042.     EVT_TASK_1 (EVENT_OBJ_SIGPAUSE, taskIdCurrent);  /* log event */
  1043. #endif
  1044.     if (windPendQPut (&qHead, WAIT_FOREVER) != OK)
  1045.         {
  1046. windExit (); /* KERNEL EXIT */
  1047. if (_func_pthread_setcanceltype != NULL)
  1048.             {
  1049.             _func_pthread_setcanceltype(savtype, NULL);
  1050.             }
  1051. return (ERROR);
  1052.         }
  1053.     windExit (); /* KERNEL EXIT */
  1054.     if (_func_pthread_setcanceltype != NULL)
  1055.         {
  1056.         _func_pthread_setcanceltype(savtype, NULL);
  1057.         }
  1058.     errnoSet (EINTR);
  1059.     return (ERROR);
  1060.     }
  1061. /*******************************************************************************
  1062. *
  1063. * sigtimedwait - wait for a signal
  1064. *
  1065. * The function sigtimedwait() selects the pending signal from the set
  1066. * specified by <pSet>.  If multiple signals in <pSet> are pending, it will
  1067. * remove and return the lowest numbered one.  If no signal in <pSet> is pending
  1068. * at the
  1069. * time of the call, the task will be suspend until one of the signals in <pSet>
  1070. * become pending, it is interrupted by an unblocked caught signal, or
  1071. * until the time interval specified by <pTimeout> has expired.
  1072. * If <pTimeout> is NULL, then the timeout interval is forever.
  1073. *
  1074. * If the <pInfo> argument is non-NULL, the selected signal number is
  1075. * stored in the `si_signo' member, and the cause of the signal is
  1076. * stored in the `si_code' member.  If the signal is a queued signal,
  1077. * the value is stored in the `si_value' member of <pInfo>; otherwise
  1078. * the content of `si_value' is undefined.
  1079. *
  1080. * The following values are defined in signal.h for `si_code':
  1081. * .iP SI_USER
  1082. * the signal was sent by the kill() function.
  1083. * .iP SI_QUEUE
  1084. * the signal was sent by the sigqueue() function.
  1085. * .iP SI_TIMER
  1086. * the signal was generated by the expiration of a timer set by timer_settime().
  1087. * .iP SI_ASYNCIO
  1088. * the signal was generated by the completion of an asynchronous I/O request.
  1089. * .iP SI_MESGQ
  1090. * the signal was generated by the arrival of a message on an empty message
  1091. * queue.
  1092. * .LP
  1093. *
  1094. * The function sigtimedwait() provides a synchronous mechanism for tasks
  1095. * to wait for asynchromously generated signals.  A task should use
  1096. * sigprocmask() to block any signals it wants to handle synchronously and
  1097. * leave their signal handlers in the default state.  The task can then
  1098. * make repeated calls to sigtimedwait() to remove any signals that are
  1099. * sent to it.
  1100. *
  1101. * RETURNS: Upon successful completion (that is, one of the signals specified
  1102. * by <pSet> is pending or is generated) sigtimedwait() will return the selected
  1103. * signal number.  Otherwise, a value of -1 is returned and `errno' is set to
  1104. * indicate the error.
  1105. *
  1106. * ERRNO
  1107. * .iP EINTR
  1108. * The wait was interrupted by an unblocked, caught signal.
  1109. * .iP EAGAIN
  1110. * No signal specified by <pSet> was delivered within the specified timeout
  1111. * period.
  1112. * .iP EINVAL
  1113. * The <pTimeout> argument specified a `tv_nsec' value less than zero or greater
  1114. * than or equal to 1000 million.
  1115. *
  1116. * SEE ALSO: sigwait()
  1117. */
  1118. int sigtimedwait
  1119.     (
  1120.     const sigset_t *pSet, /* the signal mask while suspended */
  1121.     struct siginfo *pInfo, /* return value */
  1122.     const struct timespec *pTimeout
  1123.     )
  1124.     {
  1125.     struct sigtcb *pSigTcb;
  1126.     struct sigwait waitinfo;
  1127.     struct siginfo info;
  1128.     int signo;
  1129.     int wait;
  1130.     int status;
  1131.     int savtype;
  1132.     if ((pSigTcb = sigTcbGet()) == NULL)
  1133. return (ERROR); /* errno was set */
  1134.     if (_func_pthread_setcanceltype != NULL)
  1135.         {
  1136.         _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);
  1137.         }
  1138.     if (pTimeout != 0)
  1139. {
  1140. int tickRate = sysClkRateGet();
  1141. if ((pTimeout->tv_nsec < 0) || (pTimeout->tv_nsec > 1000000000))
  1142.     {
  1143.     errno = EINVAL;
  1144.     if (_func_pthread_setcanceltype != NULL)
  1145.                 {
  1146.                 _func_pthread_setcanceltype(savtype, NULL);
  1147.                 }
  1148.     return (ERROR);
  1149.     }
  1150. wait = pTimeout->tv_sec * tickRate +
  1151. pTimeout->tv_nsec / (1000000000 / tickRate);
  1152. }
  1153.     else
  1154. wait = WAIT_FOREVER;
  1155.     kernelState = TRUE; /* KERNEL ENTER */
  1156.     if ((signo = sigPendGet(pSigTcb, pSet, &info)) > 0)
  1157. {
  1158. windExit (); /* KERNEL EXIT */
  1159. if (pInfo != NULL)
  1160. *pInfo = info;
  1161.         if (_func_pthread_setcanceltype != NULL)
  1162.             {
  1163.             _func_pthread_setcanceltype(savtype, NULL);
  1164.             }
  1165. return (signo);
  1166. }
  1167.     waitinfo.sigw_set = *pSet;
  1168.     qInit (&waitinfo.sigw_wait, Q_FIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  1169.     pSigTcb->sigt_wait = &waitinfo;
  1170. #ifdef WV_INSTRUMENTATION
  1171.     /* windview - level 2 event logging */
  1172.     EVT_TASK_1 (EVENT_OBJ_SIGWAIT, waitinfo.sigw_wait);
  1173. #endif
  1174.     if (windPendQPut (&waitinfo.sigw_wait, wait) != OK)
  1175.         {
  1176. windExit (); /* KERNEL EXIT */
  1177.  
  1178.         if (_func_pthread_setcanceltype != NULL)
  1179.             {
  1180.             _func_pthread_setcanceltype(savtype, NULL);
  1181.             }
  1182.         return (ERROR);
  1183.         }
  1184.     status = windExit (); /* KERNEL EXIT */
  1185.     pSigTcb->sigt_wait = 0;
  1186.     if (status != 0)
  1187. if (_func_pthread_setcanceltype != NULL)
  1188.             {
  1189.             _func_pthread_setcanceltype(savtype, NULL);
  1190.             }
  1191. errnoSet ((status == RESTART) ? EINTR : EAGAIN);
  1192. return (-1);
  1193. }
  1194.     if (pInfo != NULL)
  1195. *pInfo = waitinfo.sigw_info;
  1196.     if (_func_pthread_setcanceltype != NULL)
  1197.         {
  1198.         _func_pthread_setcanceltype(savtype, NULL);
  1199.         }
  1200.  
  1201.     return (waitinfo.sigw_info.si_signo);
  1202.     }
  1203. /*******************************************************************************
  1204. *
  1205. * sigwaitinfo - wait for real-time signals
  1206. *
  1207. * The function sigwaitinfo() is equivalent to calling sigtimedwait() with
  1208. * <pTimeout> equal to NULL.  See that manual entry for more information.
  1209. *
  1210. * RETURNS: Upon successful completion (that is, one of the signals specified
  1211. * by <pSet> is pending or is generated) sigwaitinfo() returns the selected
  1212. * signal number.  Otherwise, a value of -1 is returned and `errno' is set to
  1213. * indicate the error.
  1214. *
  1215. * ERRNO
  1216. * .iP EINTR
  1217. * The wait was interrupted by an unblocked, caught signal.
  1218. */
  1219. int sigwaitinfo
  1220.     (
  1221.     const sigset_t *pSet, /* the signal mask while suspended */
  1222.     struct siginfo *pInfo /* return value */
  1223.     )
  1224.     {
  1225.     return (sigtimedwait (pSet, pInfo, (struct timespec *)NULL));
  1226.     }
  1227. /*******************************************************************************
  1228. *
  1229. * sigwait - wait for a signal to be delivered (POSIX)
  1230. *
  1231. * This routine waits until one of the signals specified in <pSet> is delivered
  1232. * to the calling thread. It then stores the number of the signal received in
  1233. * the the location pointed to by <pSig>.
  1234. *
  1235. * The signals in <pSet> must not be ignored on entrance to sigwait().
  1236. * If the delivered signal has a signal handler function attached, that
  1237. * function is not called.
  1238. *
  1239. * RETURNS: OK, or ERROR on failure.
  1240. *
  1241. * SEE ALSO: sigtimedwait()
  1242. */
  1243.  
  1244. int sigwait
  1245.     (
  1246.     const sigset_t *pSet,
  1247.     int *pSig
  1248.     )
  1249.     {
  1250.     struct siginfo info;
  1251.  
  1252.     if (sigtimedwait(pSet, &info, (struct timespec *)NULL) == ERROR)
  1253.         return(ERROR);
  1254.  
  1255.     *pSig = info.si_signo;
  1256.     return(OK);
  1257.     }
  1258. /********************************************************************************
  1259. *
  1260. * sigvec - install a signal handler
  1261. *
  1262. * This routine binds a signal handler routine referenced by <pVec> to a
  1263. * specified signal <sig>.  It can also be used to determine which handler,
  1264. * if any, has been bound to a particular signal:  sigvec() copies current
  1265. * signal handler information for <sig> to <pOvec> and does not install a
  1266. * signal handler if <pVec> is set to NULL (0).
  1267. *
  1268. * Both <pVec> and <pOvec> are pointers to a structure of type f3struct
  1269. * sigvecfP.  The information passed includes not only the signal handler
  1270. * routine, but also the signal mask and additional option bits.  The
  1271. * structure `sigvec' and the available options are defined in signal.h.
  1272. *
  1273. * RETURNS: OK (0), or ERROR (-1) if the signal number is invalid or the
  1274. * signal TCB cannot be allocated.
  1275. *
  1276. * ERRNO: EINVAL, ENOMEM
  1277. */
  1278. int sigvec
  1279.     (
  1280.     int sig, /* signal to attach handler to */
  1281.     const struct sigvec *pVec, /* new handler information */
  1282.     struct sigvec *pOvec /* previous handler information */
  1283.     )
  1284.     {
  1285.     struct sigaction act, oact;
  1286.     int retVal;
  1287.     if (pVec != NULL)
  1288. {
  1289. act.sa_handler = pVec->sv_handler;
  1290. act.sa_mask = pVec->sv_mask;
  1291. act.sa_flags = pVec->sv_flags;
  1292. retVal = sigaction(sig, &act, &oact);
  1293. }
  1294.     else
  1295. retVal = sigaction(sig, NULL, &oact);
  1296.     if (pOvec != NULL)
  1297. {
  1298. pOvec->sv_handler = oact.sa_handler;
  1299. pOvec->sv_mask = oact.sa_mask;
  1300. pOvec->sv_flags = oact.sa_flags;
  1301. }
  1302.     return (retVal);
  1303.     }
  1304. /*******************************************************************************
  1305. *
  1306. * sigreturn - early return from a signal handler
  1307. *
  1308. * NOMANUAL
  1309. *
  1310. */
  1311. void sigreturn
  1312.     (
  1313.     struct sigcontext *pContext
  1314.     )
  1315.     {
  1316.     (void) sigprocmask (SIG_SETMASK, &pContext->sc_mask, 0);
  1317.     _sigCtxLoad (&pContext->sc_regs);
  1318.     }
  1319. /*******************************************************************************
  1320. *
  1321. * sigsetmask - set the signal mask
  1322. *
  1323. * This routine sets the calling task's signal mask to a specified value.
  1324. * A one (1) in the bit mask indicates that the specified signal is blocked
  1325. * from delivery.  Use the macro SIGMASK to construct the mask for a specified
  1326. * signal number.
  1327. *
  1328. * RETURNS: The previous value of the signal mask.
  1329. *
  1330. * SEE ALSO: sigprocmask()
  1331. */
  1332.  
  1333. int sigsetmask
  1334.     (
  1335.     int mask /* new signal mask */
  1336.     )
  1337.     {
  1338.     sigset_t in;
  1339.     sigset_t out;
  1340.     in = (sigset_t) mask;
  1341.     (void) sigprocmask (SIG_SETMASK, &in, &out);
  1342.     return ((int) out);
  1343.     }
  1344. /*******************************************************************************
  1345. *
  1346. * sigblock - add to a set of blocked signals
  1347. *
  1348. * This routine adds the signals in <mask> to the task's set of blocked signals.
  1349. * A one (1) in the bit mask indicates that the specified signal is blocked
  1350. * from delivery.  Use the macro SIGMASK to construct the mask for a specified
  1351. * signal number.
  1352. *
  1353. * RETURNS: The previous value of the signal mask.
  1354. *
  1355. * SEE ALSO: sigprocmask()
  1356. */
  1357.  
  1358. int sigblock
  1359.     (
  1360.     int mask /* mask of additional signals to be blocked */
  1361.     )
  1362.     {
  1363.     sigset_t in;
  1364.     sigset_t out;
  1365.     in = (sigset_t) mask;
  1366.     (void) sigprocmask (SIG_BLOCK, &in, &out);
  1367.     return ((int) out);
  1368.     }
  1369. /*******************************************************************************
  1370. *
  1371. * raise - send a signal to the caller's task
  1372. *
  1373. * This routine sends the signal <signo> to the task invoking the call.
  1374. *
  1375. * RETURNS: OK (0), or ERROR (-1) if the signal number or task ID is invalid.
  1376. *
  1377. * ERRNO: EINVAL
  1378. */
  1379. int raise
  1380.     (
  1381.     int signo /* signal to send to caller's task */
  1382.     )
  1383.     {
  1384.     return (kill ((int) taskIdCurrent, signo));
  1385.     }
  1386. /*******************************************************************************
  1387. *
  1388. * kill - send a signal to a task (POSIX)
  1389. *
  1390. * This routine sends a signal <signo> to the task specified by <tid>.
  1391. *
  1392. * RETURNS: OK (0), or ERROR (-1) if the task ID or signal number is invalid.
  1393. *
  1394. * ERRNO: EINVAL
  1395. */
  1396. int kill
  1397.     (
  1398.     int tid, /* task to send signal to */
  1399.     int signo /* signal to send to task */
  1400.     )
  1401.     {
  1402.     if (!issig (signo))
  1403. {
  1404. errnoSet (EINVAL);
  1405. return (ERROR);
  1406. }
  1407. #ifdef WV_INSTRUMENTATION
  1408.     /* windview - level 1 event logging */
  1409.     EVT_OBJ_SIG (EVENT_KILL , 2, signo, tid);
  1410. #endif
  1411.     if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid))
  1412. {
  1413. if (TASK_ID_VERIFY (tid) != OK)
  1414.     {
  1415.     errnoSet (EINVAL);
  1416.     return (ERROR);
  1417.     }
  1418. excJobAdd ((VOIDFUNCPTR) kill, tid, signo, 0, 0, 0, 0);
  1419. return (OK);
  1420. }
  1421.     kernelState = TRUE; /* KERNEL ENTER */
  1422.  
  1423.     if (TASK_ID_VERIFY (tid) != OK) /* verify task */
  1424. {
  1425. windExit (); /* KERNEL EXIT */
  1426. errnoSet (EINVAL);
  1427. return (ERROR);
  1428. }
  1429.     sigWindKill ((WIND_TCB *) tid, signo); /* send signal */
  1430.  
  1431.     windExit (); /* KERNEL EXIT */
  1432.  
  1433.     return (OK);
  1434.     }
  1435. /*******************************************************************************
  1436. *
  1437. * sigqueue - send a queued signal to a task
  1438. * The function sigqueue() sends the signal specified by <signo> with
  1439. * the signal-parameter value specified by <value> to the process
  1440. * specified by <tid>.
  1441. *
  1442. * RETURNS: OK (0), or ERROR (-1) if the task ID or signal number is invalid,
  1443. * or if there are no queued-signal buffers available.
  1444. *
  1445. * ERRNO: EINVAL EAGAIN
  1446. */
  1447. int sigqueue
  1448.     (
  1449.     int tid,
  1450.     int signo,
  1451.     const union sigval value
  1452.     )
  1453.     {
  1454.     struct sigpend pend;
  1455.     if (!issig (signo))
  1456. {
  1457. errnoSet (EINVAL);
  1458. return (ERROR);
  1459. }
  1460. #ifdef WV_INSTRUMENTATION
  1461.     /* windview - level 1 event logging */
  1462.     EVT_OBJ_SIG (EVENT_KILL , 2, signo, tid);
  1463. #endif
  1464.     if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid))
  1465. {
  1466. if (TASK_ID_VERIFY (tid) != OK)
  1467.     {
  1468.     errnoSet (EINVAL);
  1469.     return (ERROR);
  1470.     }
  1471. if (_pSigQueueFreeHead == NULL)
  1472.     {
  1473.     errnoSet (EAGAIN);
  1474.     return (ERROR);
  1475.     }
  1476. excJobAdd ((VOIDFUNCPTR)sigqueue, tid, signo, value.sival_int, 0, 0, 0);
  1477. return (OK);
  1478. }
  1479.     kernelState = TRUE; /* KERNEL ENTER */
  1480.  
  1481.     if (TASK_ID_VERIFY (tid) != OK) /* verify task */
  1482. {
  1483. windExit (); /* KERNEL EXIT */
  1484. errnoSet (EINVAL);
  1485. return (ERROR);
  1486. }
  1487.     if (_pSigQueueFreeHead == NULL)
  1488. {
  1489. windExit (); /* KERNEL EXIT */
  1490. errnoSet (EAGAIN);
  1491. return (ERROR);
  1492. }
  1493.     sigPendInit (&pend);
  1494.     pend.sigp_info.si_signo = signo;
  1495.     pend.sigp_info.si_code  = SI_QUEUE;
  1496.     pend.sigp_info.si_value = value;
  1497.     sigWindPendKill ((WIND_TCB *) tid, &pend); /* signal a task */
  1498.  
  1499.     windExit (); /* KERNEL EXIT */
  1500.     return (0);
  1501.     }
  1502. /*******************************************************************************
  1503. *
  1504. * sigWrapper - trampoline code to get to users signal handler from kernel
  1505. *
  1506. */
  1507. static void sigWrapper
  1508.     (
  1509.     struct sigcontext *pContext
  1510.     )
  1511.     {
  1512.     int signo = pContext->sc_info.si_signo;
  1513.     struct sigaction *pAction =
  1514. &((taskIdCurrent->pSignalInfo))->sigt_vec[signo];
  1515.     void (*handler)() = pAction->sa_handler;
  1516. #ifdef WV_INSTRUMENTATION
  1517.     /* windview - level 1 event logging */
  1518.     EVT_OBJ_SIG (EVENT_SIGWRAPPER, 2, signo, taskIdCurrent);
  1519. #endif
  1520.     if (pAction->sa_flags & SA_RESETHAND)
  1521. (void) signal (signo, SIG_DFL);
  1522.     if (handler != SIG_DFL && handler != SIG_IGN && handler != SIG_ERR)
  1523. {
  1524. if (pAction->sa_flags & SA_SIGINFO)
  1525.     (*handler) (signo, &pContext->sc_info, pContext);
  1526. else
  1527.     (*handler) (signo, pContext->sc_info.si_value.sival_int, pContext);
  1528. }
  1529.     sigreturn (pContext);
  1530.     }
  1531. /*******************************************************************************
  1532. *
  1533. * sigTcbGet - get the pointer to the signal tcb
  1534. *
  1535. * Get the pointer to the signal tcb.  If there is no signal tcb, try and
  1536. * allocate it.
  1537. *
  1538. */
  1539. static struct sigtcb *sigTcbGet (void)
  1540.     {
  1541.     WIND_TCB *pTcb = taskIdCurrent;
  1542.     struct sigtcb *pSigTcb;
  1543.     int ix;
  1544.     if (INT_RESTRICT () != OK)
  1545. return (NULL); /* errno was set */
  1546.     if (pTcb->pSignalInfo != NULL)
  1547. return (pTcb->pSignalInfo);
  1548.     pSigTcb = (struct sigtcb *) taskStackAllot((int) taskIdCurrent,
  1549.        sizeof (struct sigtcb));
  1550.     if (pSigTcb == NULL)
  1551. {
  1552. errnoSet (ENOMEM);
  1553. return (NULL);
  1554. }
  1555.     pTcb->pSignalInfo = pSigTcb;
  1556.     bzero ((void *) pSigTcb, sizeof (struct sigtcb));
  1557.     for (ix = 0; ix <= _NSIGS; ix++)
  1558. pSigTcb->sigt_qhead[ix].sigq_next = pSigTcb->sigt_qhead[ix].sigq_prev =
  1559. &pSigTcb->sigt_qhead[ix];
  1560.     return (pSigTcb);
  1561.     }
  1562. /*******************************************************************************
  1563. *
  1564. * sigPendRun - get a signal from the set of pending signals and run it
  1565. *
  1566. * NOTE: YOU MUST BE IN THE KERNEL.
  1567. */
  1568. static int sigPendRun
  1569.     (
  1570.     struct sigtcb *pSigTcb
  1571.     )
  1572.     {
  1573.     sigset_t set = ~pSigTcb->sigt_blocked;
  1574.     struct sigcontext sigCtx;
  1575.     int signo;
  1576.     if ((signo = sigPendGet (pSigTcb, &set, &sigCtx.sc_info)) > 0)
  1577. {
  1578. sigCtx.sc_onstack      = 0;
  1579. sigCtx.sc_restart      = 0;
  1580. sigCtx.sc_mask         = pSigTcb->sigt_blocked;
  1581. pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask |
  1582.   sigmask(signo));
  1583. #if CPU_FAMILY == MC680X0
  1584. sigCtx.sc_fformat      = 0;
  1585. #endif
  1586. windExit (); /* KERNEL EXIT */
  1587. if (_sigCtxSave (&sigCtx.sc_regs) == 0)
  1588.     {
  1589.     _sigCtxRtnValSet (&sigCtx.sc_regs, 1);
  1590.     sigWrapper (&sigCtx);
  1591.     }
  1592. return (TRUE);
  1593. }
  1594.     return (FALSE);
  1595.     }
  1596. /*******************************************************************************
  1597. *
  1598. * sigPendGet - get a signal from the set of pending signals
  1599. *
  1600. * NOTE: YOU MUST BE IN THE KERNEL.
  1601. */
  1602. static int sigPendGet
  1603.     (
  1604.     struct sigtcb *pSigTcb,
  1605.     const sigset_t *sigset,
  1606.     struct siginfo  *info
  1607.     )
  1608.     {
  1609.     long sig;
  1610.     long mask;
  1611.     struct sigpend *pSigpend;
  1612.     mask = *sigset & pSigTcb->sigt_pending;
  1613.     if (mask == 0)
  1614. return (OK);
  1615.     mask &= -mask; /* find lowest bit set */
  1616.     sig = ffsMsb (mask);
  1617.     if (mask & pSigTcb->sigt_kilsigs)
  1618. {
  1619. pSigTcb->sigt_kilsigs &= ~mask;
  1620. info->si_signo = sig;
  1621. info->si_code = SI_KILL;
  1622. info->si_value.sival_int = 0;
  1623. }
  1624.     else
  1625. {
  1626. pSigpend = structbase(struct sigpend, sigp_q,
  1627.       pSigTcb->sigt_qhead[sig].sigq_next);
  1628. pSigpend->sigp_q.sigq_prev->sigq_next = pSigpend->sigp_q.sigq_next;
  1629. pSigpend->sigp_q.sigq_next->sigq_prev = pSigpend->sigp_q.sigq_prev;
  1630. pSigpend->sigp_q.sigq_next = NULL;
  1631. pSigpend->sigp_q.sigq_prev = NULL;
  1632. *info = pSigpend->sigp_info;
  1633. pSigpend->sigp_overruns = pSigpend->sigp_active_overruns;
  1634. pSigpend->sigp_active_overruns = 0;
  1635. /*
  1636.  * free queued signal buffer
  1637.  */
  1638. if (pSigpend->sigp_info.si_code == SI_QUEUE)
  1639.     {
  1640.     *(struct sigpend **)pSigpend = _pSigQueueFreeHead;
  1641.     _pSigQueueFreeHead = pSigpend;
  1642.     }
  1643. }
  1644.     if (pSigTcb->sigt_qhead[sig].sigq_next == &pSigTcb->sigt_qhead[sig])
  1645. pSigTcb->sigt_pending &= ~mask;
  1646.     return (sig);
  1647.     }
  1648. /*******************************************************************************
  1649. *
  1650. * sigWindPendKill - add a signal to the set of pending signals
  1651. *
  1652. * NOTE: YOU MUST BE IN THE KERNEL.
  1653. */
  1654. static void sigWindPendKill
  1655.     (
  1656.     WIND_TCB *pTcb,
  1657.     struct sigpend *pSigPend
  1658.     )
  1659.     {
  1660.     int signo = pSigPend->sigp_info.si_signo;
  1661.     struct sigtcb *pSigTcb;
  1662.     void (*func)();
  1663.     unsigned mask;
  1664.     /*
  1665.      * Check to see if the task has the signal structure.  If it does
  1666.      * not, we pretend the task is ignoring them.
  1667.      */
  1668.     if ((pSigTcb = pTcb->pSignalInfo) == NULL)
  1669. return;
  1670.     /*
  1671.      * If task is waiting for signal, deliver it by waking up the task.
  1672.      */
  1673.     if ((pSigTcb->sigt_wait != NULL) &&
  1674. (sigismember(&pSigTcb->sigt_wait->sigw_set, signo) == 1) &&
  1675. (Q_FIRST(&pSigTcb->sigt_wait->sigw_wait) != NULL))
  1676. {
  1677. pSigTcb->sigt_wait->sigw_info = pSigPend->sigp_info;
  1678. #ifdef WV_INSTRUMENTATION
  1679.         /* windview - level 2 event logging */
  1680.    EVT_TASK_1 (EVENT_OBJ_SIGKILL, pTcb); /* log event */
  1681. #endif
  1682. windPendQGet (&pSigTcb->sigt_wait->sigw_wait);
  1683. /*
  1684.  * Mark task as no longer waiting
  1685.  */
  1686. pSigTcb->sigt_wait = NULL;
  1687. return;
  1688. }
  1689.     /*
  1690.      * The default action for signals is to ignore them, in posix
  1691.      * it is to kill the process.
  1692.      */
  1693.     func = pSigTcb->sigt_vec[signo].sa_handler;
  1694.     if (func == SIG_DFL)
  1695. return; /* should maybe kill the task */
  1696.     /*
  1697.      * Check to see if signal should be ignored.
  1698.      */
  1699.     if (func == SIG_IGN)
  1700. return;
  1701.     /*
  1702.      * Check to see if signal should be queued up because they are being
  1703.      * blocked.
  1704.      */
  1705.     mask = sigmask(signo);
  1706.     if (pSigTcb->sigt_blocked & mask)
  1707. {
  1708. /*
  1709.  * kill signals just get a bit to say a signal has come
  1710.  */
  1711. if (pSigPend->sigp_info.si_code == SI_KILL)
  1712.     {
  1713.     pSigTcb->sigt_kilsigs |= mask;
  1714.     pSigTcb->sigt_pending |= mask;
  1715.     }
  1716. /*
  1717.  * if the signal is all ready queued, mark it as overrun
  1718.  */
  1719. else if (pSigPend->sigp_q.sigq_next != NULL)
  1720.     pSigPend->sigp_active_overruns++;
  1721. /*
  1722.  * must be a signal to queue
  1723.  */
  1724. else
  1725.     {
  1726.     struct sigq *head = &pSigTcb->sigt_qhead[signo];
  1727.     /*
  1728.      * alloc buffer for sigqueue
  1729.      */
  1730.     if (pSigPend->sigp_info.si_code == SI_QUEUE)
  1731. {
  1732. struct sigpend *pTmp = _pSigQueueFreeHead;
  1733. _pSigQueueFreeHead = *(struct sigpend **)_pSigQueueFreeHead;
  1734. *pTmp = *pSigPend;
  1735. pSigPend = pTmp;
  1736. }
  1737.     pSigPend->sigp_q.sigq_prev = head->sigq_prev;
  1738.     pSigPend->sigp_q.sigq_next = head;
  1739.     pSigPend->sigp_q.sigq_prev->sigq_next = &pSigPend->sigp_q;
  1740.     head->sigq_prev = &pSigPend->sigp_q;
  1741.     pSigTcb->sigt_pending |= mask;
  1742.     pSigPend->sigp_tcb = pSigTcb;
  1743.     }
  1744. return;
  1745. }
  1746.     /*
  1747.      * Force delivery of the signal.
  1748.      */
  1749.     if (taskIdCurrent != pTcb)
  1750. {
  1751. int args[2];
  1752. struct sigcontext *pCtx;
  1753. #if _STACK_DIR == _STACK_GROWS_DOWN
  1754. pCtx = (struct sigcontext *) MEM_ROUND_DOWN
  1755.        (((struct sigcontext *)_sigCtxStackEnd (&pTcb->regs)) - 1);
  1756. #else
  1757. taskRegsStackToTcb (pTcb);
  1758. pCtx = (struct sigcontext *)
  1759.      MEM_ROUND_UP(_sigCtxStackEnd (&pTcb->regs));
  1760. #endif
  1761. args[0] = 1;
  1762. args[1] = (int)pCtx;
  1763. /*
  1764.  * Mark task as no longer waiting
  1765.  */
  1766. pSigTcb->sigt_wait     = NULL;
  1767. pCtx->sc_onstack       = 0;
  1768. pCtx->sc_restart       = sigWindRestart (pTcb);
  1769. pCtx->sc_mask          = pSigTcb->sigt_blocked;
  1770. pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask | mask);
  1771. pCtx->sc_info          = pSigPend->sigp_info;
  1772. pCtx->sc_regs          = pTcb->regs;
  1773. #if CPU_FAMILY == MC680X0
  1774. pCtx->sc_fformat = pTcb->foroff;
  1775. #endif
  1776. #if CPU == I960KB
  1777. bcopy (pTcb->intResumptionRec, pCtx->sc_resumption, 16);
  1778. #endif
  1779. pCtx->sc_pregs         = pSigPend->sigp_pregs;
  1780. #if _STACK_DIR == _STACK_GROWS_DOWN
  1781. _sigCtxSetup (&pTcb->regs, (void *)STACK_ROUND_DOWN(pCtx), sigWrapper, args);
  1782. #else
  1783. _sigCtxSetup (&pTcb->regs, (void *)STACK_ROUND_UP(pCtx + 1), sigWrapper, args);
  1784. #endif
  1785. }
  1786.     else
  1787. {
  1788. struct sigcontext Ctx;
  1789. Ctx.sc_onstack         = 0;
  1790. Ctx.sc_restart         = 0;
  1791. Ctx.sc_mask            = pSigTcb->sigt_blocked;
  1792. pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask | mask);
  1793. Ctx.sc_info            = pSigPend->sigp_info;
  1794. #if CPU_FAMILY == MC680X0
  1795. Ctx.sc_fformat         = pTcb->foroff;
  1796. #endif
  1797. #if CPU == I960KB
  1798. bcopy (pTcb->intResumptionRec, Ctx.sc_resumption, 16);
  1799. #endif
  1800. Ctx.sc_pregs           = pSigPend->sigp_pregs;
  1801. windExit (); /* KERNEL EXIT */
  1802. if (_sigCtxSave(&Ctx.sc_regs) == 0)
  1803.     {
  1804.     _sigCtxRtnValSet (&Ctx.sc_regs, 1);
  1805.     sigWrapper(&Ctx);
  1806.     }
  1807. kernelState = TRUE; /* KERNEL ENTER */
  1808. }
  1809.     }
  1810. /*******************************************************************************
  1811. *
  1812. * sigPendKill - send a queue signal
  1813. *
  1814. * NOMANUAL
  1815. *
  1816. * RETURNS: nothing
  1817. */
  1818. int sigPendKill
  1819.     (
  1820.     int tid,
  1821.     struct sigpend *pSigPend
  1822.     )
  1823.     {
  1824. #if 0
  1825.     /*
  1826.      * for now, blindly assume it is valid.
  1827.      */
  1828.     if (!issig (pSigPend))
  1829. {
  1830. errnoSet (EINVAL);
  1831. return (ERROR);
  1832. }
  1833. #endif
  1834.     if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid))
  1835. {
  1836. if (TASK_ID_VERIFY (tid) != OK)
  1837.     {
  1838.     errnoSet (EINVAL);
  1839.     return (ERROR);
  1840.     }
  1841. excJobAdd ((VOIDFUNCPTR) sigPendKill, tid, (int) pSigPend, 0, 0, 0, 0);
  1842. return (OK);
  1843. }
  1844.     kernelState = TRUE; /* KERNEL ENTER */
  1845.  
  1846.     if (TASK_ID_VERIFY (tid) != OK) /* verify task */
  1847. {
  1848. windExit (); /* KERNEL EXIT */
  1849. errnoSet (EINVAL);
  1850. return (ERROR);
  1851. }
  1852.     sigWindPendKill ((WIND_TCB *) tid, pSigPend); /* signal a task */
  1853.  
  1854.     windExit (); /* KERNEL EXIT */
  1855.  
  1856.     return (OK);
  1857.     }
  1858. /*******************************************************************************
  1859. *
  1860. * sigPendInit - init a queue signal
  1861. *
  1862. * NOMANUAL
  1863. *
  1864. * RETURNS: nothing
  1865. */
  1866. void sigPendInit
  1867.     (
  1868.     struct sigpend *pSigPend
  1869.     )
  1870.     {
  1871.     pSigPend->sigp_q.sigq_prev = pSigPend->sigp_q.sigq_next = NULL;
  1872.     pSigPend->sigp_overruns = 0; 
  1873.     pSigPend->sigp_pregs = NULL; 
  1874.     }
  1875. /*******************************************************************************
  1876. *
  1877. * sigPendDestroy - destory a queue signal
  1878. *
  1879. * NOMANUAL
  1880. *
  1881. * RETURNS: OK or ERROR
  1882. */
  1883. int sigPendDestroy
  1884.     (
  1885.     struct sigpend *pSigPend
  1886.     )
  1887.     {
  1888.     if (INT_RESTRICT () != OK)
  1889. return (ERROR);
  1890.     pSigPend->sigp_overruns = 0; 
  1891.     kernelState = TRUE; /* KERNEL ENTER */
  1892.     if (pSigPend->sigp_q.sigq_next != 0)
  1893. {
  1894. /*
  1895.  * Clear sigpending if last one on chain. (and there was no kilsigs)
  1896.  */
  1897. if (pSigPend->sigp_q.sigq_next == pSigPend->sigp_q.sigq_prev)
  1898.     pSigPend->sigp_tcb->sigt_pending &=
  1899.      (pSigPend->sigp_tcb->sigt_kilsigs |
  1900. ~sigmask(pSigPend->sigp_info.si_signo));
  1901. pSigPend->sigp_q.sigq_next->sigq_prev = pSigPend->sigp_q.sigq_prev;
  1902. pSigPend->sigp_q.sigq_prev->sigq_next = pSigPend->sigp_q.sigq_next;
  1903. pSigPend->sigp_q.sigq_prev = pSigPend->sigp_q.sigq_next = NULL;
  1904. }
  1905.     windExit (); /* KERNEL EXIT */
  1906.     return (OK);
  1907.     }
  1908. /*******************************************************************************
  1909. *
  1910. * sigWindKill - do the dirty work of sending a signal.
  1911. *
  1912. * NOTE: YOU MUST BE IN THE KERNEL.
  1913. */
  1914. static void sigWindKill
  1915.     (
  1916.     WIND_TCB *pTcb,
  1917.     int signo
  1918.     )
  1919.     {
  1920.     struct sigpend pend;
  1921.     pend.sigp_info.si_signo       = signo;
  1922.     pend.sigp_info.si_code            = SI_KILL;
  1923.     pend.sigp_info.si_value.sival_int = 0;
  1924.     sigWindPendKill(pTcb, &pend);
  1925.     }
  1926. /*******************************************************************************
  1927. *
  1928. * sigWindRestart - test the state of a task
  1929. *
  1930. * Test the state of a task you are sending a signal to.  If it is
  1931. * pended, tell it to restart itself after it has returned.
  1932. *
  1933. * NOTE: YOU MUST BE IN THE KERNEL.
  1934. */
  1935. static int sigWindRestart
  1936.     (
  1937.     WIND_TCB *pTcb
  1938.     )
  1939.     {
  1940.     int delay = WAIT_FOREVER;
  1941.     int status; /* Q_REMOVE return value */
  1942.     if ((pTcb->status & (WIND_PEND | WIND_DELAY)) != 0)
  1943. {
  1944. taskRtnValueSet (pTcb, RESTART);
  1945. if ((pTcb->status & WIND_DELAY) != 0)
  1946.     {
  1947.     pTcb->status &= ~WIND_DELAY;
  1948.     Q_REMOVE (&tickQHead, &pTcb->tickNode); /* remove from queue */
  1949.     delay = Q_KEY (&tickQHead, &pTcb->tickNode, 1);
  1950.     }
  1951. if ((pTcb->status & WIND_PEND) != 0)
  1952.     {
  1953.     pTcb->pPriMutex = NULL; /* clear pPriMutex */
  1954.     pTcb->status   &= ~WIND_PEND; /* turn off pend bit */
  1955.     status = Q_REMOVE (pTcb->pPendQ, pTcb); /* out of pend queue */
  1956.     /* 
  1957.      * If task was pended on a shared semaphore its shared TCB 
  1958.      * could have been remove by a semGive on another CPU.  In that 
  1959.      * case Q_REMOVE returns ALREADY_REMOVED, What we have to do
  1960.      * is set task return value to OK to avoid task to be restarted.
  1961.      * Q_REMOVE can also return ERROR if it was unable to take 
  1962.      * the shared semaphore lock to remove the shared TCB.
  1963.      * In that case we set task return value to ERROR and 
  1964.      * errorStatus to S_smObjLib_LOCK_TIMEOUT.
  1965.      */
  1966.     switch (status)
  1967. {
  1968. case ALREADY_REMOVED :
  1969.     {
  1970.     taskRtnValueSet (pTcb, OK);
  1971.     break;
  1972.     }
  1973. case ERROR :
  1974.     {
  1975.     taskRtnValueSet (pTcb, ERROR);
  1976.     pTcb->errorStatus = S_smObjLib_LOCK_TIMEOUT;
  1977.     break;
  1978.     }
  1979. }
  1980.     }
  1981. if (pTcb->status == WIND_READY) /* task is now ready */
  1982.     Q_PUT (&readyQHead, pTcb, pTcb->priority);
  1983. }
  1984.     return (delay);
  1985.     }
  1986. /*******************************************************************************
  1987. *
  1988. * sigExcSend - signal a task that has an exception
  1989. *
  1990. * RETURNS: nothing
  1991. */
  1992. static void sigExcSend
  1993.     (
  1994.     int signo,
  1995.     int code,
  1996.     REG_SET *pRegSet
  1997.     )
  1998.     {
  1999.     struct sigpend pend;
  2000.     REG_SET *pTmpRegSet;
  2001.     pTmpRegSet = taskIdCurrent->pExcRegSet;
  2002.     taskIdCurrent->pExcRegSet = 0;
  2003.     sigPendInit (&pend);
  2004.     pend.sigp_info.si_signo       = signo;
  2005.     pend.sigp_info.si_code            = SI_SYNC;
  2006.     pend.sigp_info.si_value.sival_int = code;
  2007.     pend.sigp_pregs                   = pRegSet;
  2008.     sigPendKill ((int) taskIdCurrent, &pend);
  2009.     sigPendDestroy (&pend);
  2010.     taskIdCurrent->pExcRegSet = pTmpRegSet;
  2011.     }
  2012. /*******************************************************************************
  2013. *
  2014. * sigExcKill - signal a task that has an exception
  2015. *
  2016. * RETURNS: nothing
  2017. */
  2018. static void sigExcKill
  2019.     (
  2020.     int      faultType,
  2021.     int      code,
  2022.     REG_SET  *pRegSet
  2023.     )
  2024.     {
  2025.     extern struct sigfaulttable _sigfaulttable[];
  2026.     struct sigfaulttable *pFTab;
  2027.     for (pFTab = &_sigfaulttable[0]; 
  2028.  !((pFTab->sigf_fault == 0) && (pFTab->sigf_signo == 0));
  2029.  pFTab++)
  2030. {
  2031. if (pFTab->sigf_fault == faultType)
  2032.     {
  2033.     sigExcSend (pFTab->sigf_signo, code, pRegSet);
  2034.     return;
  2035.     }
  2036. }
  2037.     /* not found in the table */
  2038.     if (pFTab->sigf_signo != 0)
  2039.         sigExcSend (pFTab->sigf_signo, code, pRegSet);
  2040. #if (CPU_FAMILY == SH)
  2041.     /* XXX  Here `pFTab' always points at the last member {0, 0}
  2042.      * XXX  in `_sigfaulttable[]'.  Therefore the above `sigExcSend()'
  2043.      * XXX  for any `not found in the table' case is useless.
  2044.      */
  2045.     {
  2046.     /* XXX  excBErrVecInit() initializes `excBErrVecNum', thus it cannot
  2047.      * XXX  be hard-coded in `_sigfaulttable[]'.  One idea is to modify
  2048.      * XXX  the above `for(;;)' looping condition and to have the
  2049.      * XXX  `not found in the table' case effective for a generic signal
  2050.      * XXX  catcher like {0, SIGBUS}.  However, {0, SIGILL} is defined
  2051.      * XXX  as a valid member for i86 architecture, so let's treat the
  2052.      * XXX  bus timeout error at outside of `_sigfaulttable[]':
  2053.      */
  2054.     IMPORT int excBErrVecNum;
  2055.     if ((excBErrVecNum != 0) && (faultType == excBErrVecNum))
  2056. sigExcSend (SIGBUS, code, pRegSet);
  2057.     }
  2058. #endif
  2059.     }