sig.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* ==== sig.c =======================================================
  2.  * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by Chris Provenzano.
  16.  * 4. The name of Chris Provenzano may not be used to endorse or promote 
  17.  *   products derived from this software without specific prior written
  18.  *   permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
  21.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
  24.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  26.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  28.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  30.  * SUCH DAMAGE.
  31.  *
  32.  * Description : All the thread signal functions.
  33.  *
  34.  *  1.32 94/06/12 proven
  35.  *      -Started coding this file.
  36.  */
  37. #ifndef lint
  38. static const char rcsid[] = "$Id$";
  39. #endif
  40. #include <errno.h>
  41. #include <pthread.h>
  42. #include <signal.h>
  43. #include <string.h>
  44. #if defined(M_UNIX)
  45. #define signal(A,B) machdep_sys_signal((A),(B))
  46. #endif
  47. extern void sig_handler_real();
  48. struct pthread * pthread_sigwait;
  49. static sigset_t pending_signals;
  50. struct pthread_sigvec {
  51. void  (*vector)();
  52. sigset_t mask;
  53. int flags;
  54. } pthread_sigvec[SIGMAX];
  55. /* ==========================================================================
  56.  * pthread_sig_register()
  57.  *
  58.  * Assumes the kernel is locked.
  59.  */
  60. int pthread_sig_register(int sig)
  61. {
  62. struct pthread ** pthread_ptr, * pthread;
  63. int ret; 
  64. /*
  65.  * If we have a siginfo structure and the signal is synchronous then
  66.  * only deliver the signal to the current thread.
  67.  */
  68. /* Check waiting threads for delivery */
  69. for (pthread_ptr = &pthread_sigwait; (*pthread_ptr);
  70.   pthread_ptr = &((*pthread_ptr)->next)) {
  71. if (sigismember((*pthread_ptr)->data.sigwait, sig)) {
  72. pthread=*pthread_ptr;
  73. *pthread_ptr=(*pthread_ptr)->next;
  74. pthread_prio_queue_enq(pthread_current_prio_queue, pthread);
  75. ret = pthread->pthread_priority;
  76. *(int *)(pthread->ret) = sig;
  77. pthread->state = PS_RUNNING;
  78. return(ret);
  79. }
  80. }
  81. /* Check current running thread */
  82. if (pthread_run) {
  83. if (!sigismember(&pthread_run->sigmask, sig)) {
  84. sigaddset(&pthread_run->sigpending, sig);
  85. pthread_run->sigcount++;
  86. return(0);
  87. }
  88. }
  89. /* Check any running thread */
  90. for (pthread = pthread_current_prio_queue->next;
  91.   pthread; pthread = pthread->next) {
  92. if (!sigismember(&pthread->sigmask, sig)) {
  93. sigaddset(&pthread->sigpending, sig);
  94. pthread->sigcount++;
  95. return(0);
  96. }
  97. }
  98. /* Check any thread */
  99. for (pthread = pthread_link_list; pthread; pthread = pthread->pll) {
  100. if (!sigismember(&pthread->sigmask, sig)) {
  101. sigaddset(&pthread->sigpending, sig);
  102. pthread->sigcount++;
  103. return(0);
  104. }
  105. }
  106. sigaddset(&pending_signals, sig);
  107. return(0);
  108. }
  109. /* ==========================================================================
  110.  * pthread_sig_default()
  111.  */
  112. void pthread_sig_default(int sig)
  113. {
  114. sigset_t mask, omask;
  115. if (pthread_sigvec[sig].vector == SIG_DFL) {
  116. /* Set the signal handler to default before issueing the kill */
  117. signal(sig, SIG_DFL);
  118. kill(getpid(), sig);
  119. sigemptyset(&mask);
  120. sigaddset(&mask, sig);
  121. machdep_sys_sigprocmask(SIG_UNBLOCK, &mask, &omask); 
  122. signal(sig, sig_handler_real);
  123. }
  124. }
  125. /* ==========================================================================
  126.  * pthread_sig_process()
  127.  *
  128.  * Assumes the kernel is locked.
  129.  */
  130. void pthread_sig_process()
  131. {
  132.   void (*vector)();
  133.   int i, j;
  134.   for (i = 1; i < SIGMAX; i++) {
  135.     if (sigismember(&(pthread_run->sigpending), i)) {
  136.       if (! sigismember(&(pthread_run->sigmask), i)) {
  137. sigdelset(&(pthread_run->sigpending), i);
  138. pthread_run->sigcount--;
  139. if (pthread_sigvec[i].vector == SIG_IGN) {
  140.   continue;
  141. if (pthread_sigvec[i].vector == SIG_DFL) {
  142.   pthread_sig_default(i);
  143.   continue;
  144. {
  145.   sigset_t omask;
  146.   sigemptyset(&omask);
  147.   /* Save old mask */
  148.   for (j = 1; j < SIGMAX; j++) {
  149.     if (sigismember(&(pthread_run->sigmask), j)) {
  150.       if (sigismember(&(pthread_sigvec[i].mask), j)) 
  151. sigaddset(&(pthread_run->sigmask), j);
  152.       sigaddset(&omask, j);
  153.     }
  154.   }
  155.   /* The signal is masked while handling the signal */
  156.   sigaddset(&(pthread_run->sigmask), i);
  157.   /* 
  158.    * Allow interrupts during a signal, 
  159.    * but not a change in the vector 
  160.    */
  161.   vector = pthread_sigvec[i].vector;
  162.   if (--pthread_kernel_lock) {
  163.     PANIC();
  164.   }
  165.   vector(i);
  166.   pthread_run->sighandled=1; /* Mark for select; Monty */
  167.   pthread_kernel_lock++;
  168.   memcpy(&(pthread_run->sigmask), &omask, sizeof(omask));
  169.       }
  170.     }
  171.   }
  172. }
  173. /* ==========================================================================
  174.  * pthread_sigmask()
  175.  *
  176.  * It is unclear wheather this call should be implemented as an atomic
  177.  * operation. The resulting mask could be wrong if in the signal
  178.  * handler the thread calls sigprocmask for any signal other than the
  179.  * signal the handler is dealing with.
  180.  */
  181. int pthread_sigmask(int how, const sigset_t *set, sigset_t * oset)
  182. {
  183. int i;
  184. if (oset) {
  185. sigemptyset(oset);
  186. for (i = 1; i < SIGMAX; i++) {
  187. if (sigismember(&(pthread_run->sigmask), i)) {
  188. sigaddset(oset, i);
  189. }
  190. }
  191. }
  192. if (set) {
  193. switch(how) {
  194. case SIG_BLOCK:
  195. for (i = 1; i < SIGMAX; i++) {
  196. if (sigismember(set, i)) {
  197. sigaddset(&(pthread_run->sigmask), i);
  198. }
  199. }
  200. break;
  201. case SIG_UNBLOCK:
  202. pthread_sched_prevent();
  203. for (i = 1; i < SIGMAX; i++) {
  204. if (sigismember(set, i)) {
  205. sigdelset(&(pthread_run->sigmask), i);
  206. if (sigismember(&pending_signals, i)) {
  207. sigaddset(&(pthread_run->sigpending), i);
  208. sigdelset(&pending_signals, i);
  209. pthread_run->sigcount++;
  210. }
  211. }
  212. }
  213. pthread_sched_resume();
  214. break;
  215. case SIG_SETMASK:
  216. sigfillset(&(pthread_run->sigmask));
  217. pthread_sched_prevent();
  218. for (i = 1; i < SIGMAX; i++) {
  219. if (! sigismember(set, i)) {
  220. sigdelset(&(pthread_run->sigmask), i);
  221. if (sigismember(&pending_signals, i)) {
  222. sigaddset(&(pthread_run->sigpending), i);
  223. sigdelset(&pending_signals, i);
  224. pthread_run->sigcount++;
  225. }
  226. }
  227. }
  228. pthread_sched_resume();
  229. break;
  230. default:
  231. SET_ERRNO(EINVAL);
  232. return(NOTOK);
  233. }
  234. }
  235. return(OK);
  236. }
  237. int sigprocmask(int how, const sigset_t *set, sigset_t * oset)
  238. {
  239. return(pthread_sigmask(how, set, oset));
  240. }
  241. /* ==========================================================================
  242.  * sigwait()
  243.  */
  244. int sigwait(const sigset_t * set, int * sig)
  245. {
  246. int i;
  247. /* Check that sig is valid */
  248. *sig = 0;
  249. pthread_sched_prevent();
  250. for (i = 1; i < SIGMAX; i++) {
  251. if (sigismember(set, i)) {
  252. /* Check personal signals */
  253. if (sigismember(&(pthread_run->sigpending), i)) {
  254. sigdelset(&(pthread_run->sigpending), i);
  255. pthread_sched_resume();
  256. *sig = i;
  257. return(OK);
  258. }
  259. /* Check kernel signals */
  260. if (sigismember(&pending_signals, i)) {
  261. sigdelset(&pending_signals, i);
  262. pthread_sched_resume();
  263. *sig = i;
  264. return(OK);
  265. }
  266. }
  267. }
  268. /* No pending signals, wait for one */
  269. pthread_run->next = pthread_sigwait;
  270. pthread_sigwait = pthread_run;
  271. pthread_run->data.sigwait = set;
  272. pthread_run->ret = sig;
  273. SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
  274. pthread_resched_resume(PS_SIGWAIT);
  275. CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
  276. return(OK);
  277. }
  278. /* ==========================================================================
  279.  * raise()
  280.  */
  281. int raise(int sig)
  282. {
  283. return(pthread_kill(pthread_self(), sig));
  284. }
  285. /* ==========================================================================
  286.  * sigsuspend()
  287.  */
  288. int sigsuspend(const sigset_t * mask)
  289. {
  290. int ret_sig, ret;
  291. sigset_t nm, om;
  292. sigfillset(&nm);
  293. for(ret_sig = 1; ret_sig < SIGMAX; ret_sig++) {
  294. if (sigismember(mask, ret_sig)) {
  295. sigdelset(&nm, ret_sig);
  296. }
  297. }
  298. pthread_sigmask(SIG_BLOCK, &nm, &om);
  299. if ((ret = sigwait(&nm, &ret_sig)) == OK) {
  300. sigemptyset(&nm);
  301. sigaddset(&nm, ret_sig);
  302. pthread_kill(pthread_self(), ret_sig);
  303. pthread_sigmask(SIG_UNBLOCK, &nm, NULL);
  304. /* There is a race condition here, it's not worth worring about */
  305. pthread_sigmask(SIG_BLOCK, &nm, NULL);
  306. SET_ERRNO(EINTR);
  307. ret = NOTOK;
  308. }
  309. pthread_sigmask(SIG_SETMASK, &om, NULL);
  310. return(ret);
  311. }
  312. /* ==========================================================================
  313.  * pthread_signal()
  314.  */
  315. void (*pthread_signal(int sig, void (*dispatch)(int)))()
  316. {
  317. void (*odispatch)(int);
  318. odispatch = pthread_sigvec[sig].vector;
  319. if ((sig > 0) && (sig < SIGMAX)) {
  320. pthread_sigvec[sig].vector = dispatch;
  321. sigemptyset(&(pthread_sigvec[sig].mask));
  322. pthread_sigvec[sig].flags = 0;
  323. }
  324. return(odispatch);
  325. }
  326. /* ==========================================================================
  327.  * pthread_sigprocmask()
  328.  */
  329. int pthread_sigaction(int sig, const struct sigaction * act, 
  330.   struct sigaction * oact)
  331. {
  332. if ((sig > 0) && (sig < SIGMAX)) {
  333. if (oact) {
  334. memcpy(&(oact->sa_mask), &(pthread_sigvec[sig].mask), 
  335.   sizeof(sigset_t));
  336. oact->sa_handler = pthread_sigvec[sig].vector;
  337. oact->sa_flags = pthread_sigvec[sig].flags;
  338. }
  339. if (act) {
  340. memcpy(&(pthread_sigvec[sig].mask), &(act->sa_mask), 
  341.   sizeof(sigset_t));
  342. pthread_sigvec[sig].vector = act->sa_handler;
  343. pthread_sigvec[sig].flags = act->sa_flags;
  344. }
  345. return(OK);
  346. }
  347. SET_ERRNO(EINVAL);
  348. return(NOTOK);
  349. }
  350. /*
  351.  * The following here are stolen from BSD because I get mutiply defined
  352.  * symbols between sig.o and posix_sig.o in Sun's libc.a under Sunos 4.1.3.
  353.  * The problem is that sigprocmask() is defined in posix_sig.o, in the same
  354.  * module that a lot of other sigset-primitives are defined, and we have
  355.  * our definition of sigprocmask() here, but use those other primitives.
  356.  */
  357. #undef sigemptyset
  358. #undef sigfillset
  359. #undef sigaddset
  360. #undef sigdelset
  361. #undef sigismember
  362. static const sigset_t __sigemptyset = __SIGEMPTYSET;
  363. int sigemptyset(sigset_t *set)
  364. {
  365. *set = __sigemptyset;
  366. return (0);
  367. }
  368. static const sigset_t __sigfillset = __SIGFILLSET;
  369. int sigfillset(sigset_t * set)
  370. {
  371. *set = __sigfillset;
  372. return (0);
  373. }
  374. #define _MAXIMUM_SIG NSIG
  375. int sigaddset(sigset_t *set, int signo)
  376. {
  377. if (signo <= 0 || signo >= _MAXIMUM_SIG) {
  378. errno = EINVAL;
  379. return -1;
  380. }
  381. __SIGADDSET(set, signo);
  382. return (0);
  383. }
  384. int sigdelset(sigset_t *set, int signo)
  385. {
  386. if (signo <= 0 || signo >= _MAXIMUM_SIG) {
  387. errno = EINVAL;
  388. return -1;
  389. }
  390. __SIGDELSET(set, signo);
  391. return (0);
  392. }
  393. int sigismember(const sigset_t *set, int signo)
  394. {
  395. if (signo <= 0 || signo >= _MAXIMUM_SIG) {
  396. errno = EINVAL;
  397. return -1;
  398. }
  399. return(__SIGISMEMBER(set, signo));
  400. }