thr_suspend_np.c revision 75369
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: head/lib/libkse/thread/thr_suspend_np.c 75369 2001-04-10 04:19:21Z deischen $
33 */
34#include <errno.h>
35#include <pthread.h>
36#include "pthread_private.h"
37
38static void	finish_suspension(void *arg);
39
40__weak_reference(_pthread_suspend_np, pthread_suspend_np);
41
42/* Suspend a thread: */
43int
44_pthread_suspend_np(pthread_t thread)
45{
46	int ret;
47
48	/* Find the thread in the list of active threads: */
49	if ((ret = _find_thread(thread)) == 0) {
50		/*
51		 * Defer signals to protect the scheduling queues from
52		 * access by the signal handler:
53		 */
54		_thread_kern_sig_defer();
55
56		switch (thread->state) {
57		case PS_RUNNING:
58			/*
59			 * Remove the thread from the priority queue and
60			 * set the state to suspended:
61			 */
62			PTHREAD_PRIOQ_REMOVE(thread);
63			PTHREAD_SET_STATE(thread, PS_SUSPENDED);
64			break;
65
66		case PS_SPINBLOCK:
67		case PS_FDR_WAIT:
68		case PS_FDW_WAIT:
69		case PS_POLL_WAIT:
70		case PS_SELECT_WAIT:
71			/*
72			 * Remove these threads from the work queue
73			 * and mark the operation as interrupted:
74			 */
75			if ((thread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
76				PTHREAD_WORKQ_REMOVE(thread);
77			_thread_seterrno(thread,EINTR);
78			thread->interrupted = 1;
79
80			/* FALLTHROUGH */
81		case PS_SIGTHREAD:
82		case PS_SLEEP_WAIT:
83		case PS_WAIT_WAIT:
84		case PS_SIGSUSPEND:
85		case PS_SIGWAIT:
86			/*
87			 * Remove these threads from the waiting queue and
88			 * set their state to suspended:
89			 */
90			PTHREAD_WAITQ_REMOVE(thread);
91			PTHREAD_SET_STATE(thread, PS_SUSPENDED);
92			break;
93
94		case PS_MUTEX_WAIT:
95			/* Mark the thread as suspended and still in a queue. */
96			thread->suspended = SUSP_MUTEX_WAIT;
97
98			PTHREAD_SET_STATE(thread, PS_SUSPENDED);
99			break;
100		case PS_COND_WAIT:
101			/* Mark the thread as suspended and still in a queue. */
102			thread->suspended = SUSP_COND_WAIT;
103
104			PTHREAD_SET_STATE(thread, PS_SUSPENDED);
105			break;
106		case PS_FDLR_WAIT:
107		case PS_FDLW_WAIT:
108		case PS_FILE_WAIT:
109		case PS_JOIN:
110			/* Mark the thread as suspended: */
111			thread->suspended = SUSP_YES;
112
113			/*
114			 * Threads in these states may be in queues.
115			 * In order to preserve queue integrity, the
116			 * cancelled thread must remove itself from the
117			 * queue.  Mark the thread as interrupted and
118			 * set the state to running.  When the thread
119			 * resumes, it will remove itself from the queue
120			 * and call the suspension completion routine.
121			 */
122			thread->interrupted = 1;
123			_thread_seterrno(thread, EINTR);
124			PTHREAD_NEW_STATE(thread, PS_RUNNING);
125			thread->continuation = finish_suspension;
126			break;
127
128		case PS_DEAD:
129		case PS_DEADLOCK:
130		case PS_STATE_MAX:
131		case PS_SUSPENDED:
132			/* Nothing needs to be done: */
133			break;
134		}
135
136		/*
137		 * Undefer and handle pending signals, yielding if
138		 * necessary:
139		 */
140		_thread_kern_sig_undefer();
141	}
142	return(ret);
143}
144
145static void
146finish_suspension(void *arg)
147{
148	struct pthread	*curthread = _get_curthread();
149
150	if (curthread->suspended != SUSP_NO)
151		_thread_kern_sched_state(PS_SUSPENDED, __FILE__, __LINE__);
152}
153
154
155