]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libpthread/thread/thr_suspend_np.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / lib / libpthread / thread / thr_suspend_np.c
1 /*
2  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
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 John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER 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  * $FreeBSD$
33  */
34 #include <errno.h>
35 #ifdef _THREAD_SAFE
36 #include <pthread.h>
37 #include "pthread_private.h"
38
39 static void     finish_suspension(void *arg);
40
41 /* Suspend a thread: */
42 int
43 pthread_suspend_np(pthread_t thread)
44 {
45         int ret;
46
47         /* Find the thread in the list of active threads: */
48         if ((ret = _find_thread(thread)) == 0) {
49                 /*
50                  * Defer signals to protect the scheduling queues from
51                  * access by the signal handler:
52                  */
53                 _thread_kern_sig_defer();
54
55                 switch (thread->state) {
56                 case PS_RUNNING:
57                         /*
58                          * Remove the thread from the priority queue and
59                          * set the state to suspended:
60                          */
61                         PTHREAD_PRIOQ_REMOVE(thread);
62                         PTHREAD_SET_STATE(thread, PS_SUSPENDED);
63                         break;
64
65                 case PS_SPINBLOCK:
66                 case PS_FDR_WAIT:
67                 case PS_FDW_WAIT:
68                 case PS_POLL_WAIT:
69                 case PS_SELECT_WAIT:
70                         /*
71                          * Remove these threads from the work queue
72                          * and mark the operation as interrupted:
73                          */
74                         if ((thread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
75                                 PTHREAD_WORKQ_REMOVE(thread);
76                         _thread_seterrno(thread,EINTR);
77                         thread->interrupted = 1;
78
79                         /* FALLTHROUGH */
80                 case PS_SIGTHREAD:
81                 case PS_SLEEP_WAIT:
82                 case PS_WAIT_WAIT:
83                 case PS_SIGSUSPEND:
84                 case PS_SIGWAIT:
85                         /*
86                          * Remove these threads from the waiting queue and
87                          * set their state to suspended:
88                          */
89                         PTHREAD_WAITQ_REMOVE(thread);
90                         PTHREAD_SET_STATE(thread, PS_SUSPENDED);
91                         break;
92
93                 case PS_MUTEX_WAIT:
94                 case PS_COND_WAIT:
95                 case PS_FDLR_WAIT:
96                 case PS_FDLW_WAIT:
97                 case PS_FILE_WAIT:
98                 case PS_JOIN:
99                         /* Mark the thread as suspended: */
100                         thread->suspended = 1;
101
102                         /*
103                          * Threads in these states may be in queues.
104                          * In order to preserve queue integrity, the
105                          * cancelled thread must remove itself from the
106                          * queue.  Mark the thread as interrupted and
107                          * set the state to running.  When the thread
108                          * resumes, it will remove itself from the queue
109                          * and call the suspension completion routine.
110                          */
111                         thread->interrupted = 1;
112                         _thread_seterrno(thread, EINTR);
113                         PTHREAD_NEW_STATE(thread, PS_RUNNING);
114                         thread->continuation = finish_suspension;
115                         break;
116
117                 case PS_DEAD:
118                 case PS_DEADLOCK:
119                 case PS_STATE_MAX:
120                 case PS_SUSPENDED:
121                         /* Nothing needs to be done: */
122                         break;
123                 }
124
125                 /*
126                  * Undefer and handle pending signals, yielding if
127                  * necessary:
128                  */
129                 _thread_kern_sig_undefer();
130         }
131         return(ret);
132 }
133
134 static void
135 finish_suspension(void *arg)
136 {
137         if (_thread_run->suspended != 0)
138                 _thread_kern_sched_state(PS_SUSPENDED, __FILE__, __LINE__);
139 }
140
141
142 #endif