Deleted Added
full compact
thr_exit.c (127523) thr_exit.c (129484)
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

--- 15 unchanged lines hidden (view full) ---

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 *
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

--- 15 unchanged lines hidden (view full) ---

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/libthr/thread/thr_exit.c 127523 2004-03-28 14:05:28Z mtm $
32 * $FreeBSD: head/lib/libthr/thread/thr_exit.c 129484 2004-05-20 12:06:16Z mtm $
33 */
34#include <errno.h>
35#include <unistd.h>
36#include <fcntl.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <pthread.h>

--- 50 unchanged lines hidden (view full) ---

91 * This still isn't quite correct because we don't account
92 * for held spinlocks (see libc/stdlib/malloc.c).
93 */
94}
95
96void
97_pthread_exit(void *status)
98{
33 */
34#include <errno.h>
35#include <unistd.h>
36#include <fcntl.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <pthread.h>

--- 50 unchanged lines hidden (view full) ---

91 * This still isn't quite correct because we don't account
92 * for held spinlocks (see libc/stdlib/malloc.c).
93 */
94}
95
96void
97_pthread_exit(void *status)
98{
99 pthread_t pthread, joiner;
99 struct pthread *pthread;
100 int exitNow = 0;
101
100 int exitNow = 0;
101
102 /*
103 * This thread will no longer handle any signals.
104 */
105 _thread_sigblock();
106
102 /* Check if this thread is already in the process of exiting: */
107 /* Check if this thread is already in the process of exiting: */
103 if ((curthread->flags & PTHREAD_EXITING) != 0) {
108 if (curthread->exiting) {
104 char msg[128];
105 snprintf(msg, sizeof(msg), "Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",curthread);
106 PANIC(msg);
107 }
108
109 /* Flag this thread as exiting: */
109 char msg[128];
110 snprintf(msg, sizeof(msg), "Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",curthread);
111 PANIC(msg);
112 }
113
114 /* Flag this thread as exiting: */
110 curthread->flags |= PTHREAD_EXITING;
115 curthread->exiting = 1;
111
112 /* Save the return value: */
113 curthread->ret = status;
114
115 while (curthread->cleanup != NULL) {
116 pthread_cleanup_pop(1);
117 }
118 if (curthread->attr.cleanup_attr != NULL) {

--- 6 unchanged lines hidden (view full) ---

125 }
126
127 /*
128 * Remove read-write lock list. It is allocated as-needed.
129 * Therefore, it must be checked for validity before freeing.
130 */
131 if (curthread->rwlockList != NULL)
132 free(curthread->rwlockList);
116
117 /* Save the return value: */
118 curthread->ret = status;
119
120 while (curthread->cleanup != NULL) {
121 pthread_cleanup_pop(1);
122 }
123 if (curthread->attr.cleanup_attr != NULL) {

--- 6 unchanged lines hidden (view full) ---

130 }
131
132 /*
133 * Remove read-write lock list. It is allocated as-needed.
134 * Therefore, it must be checked for validity before freeing.
135 */
136 if (curthread->rwlockList != NULL)
137 free(curthread->rwlockList);
133retry:
134 /*
135 * Proper lock order, to minimize deadlocks, between joining
136 * and exiting threads is: DEAD_LIST, THREAD_LIST, exiting, joiner.
137 * In order to do this *and* protect from races, we must resort
138 * this test-and-retry loop.
139 */
140 joiner = curthread->joiner;
141
142 /* Lock the dead list first to maintain correct lock order */
143 DEAD_LIST_LOCK;
144 THREAD_LIST_LOCK;
138
139 /* Lock the dead list first to maintain correct lock order */
140 DEAD_LIST_LOCK;
141 THREAD_LIST_LOCK;
145 _thread_critical_enter(curthread);
146
142
147 if (joiner != curthread->joiner) {
148 _thread_critical_exit(curthread);
149 THREAD_LIST_UNLOCK;
150 DEAD_LIST_UNLOCK;
151 goto retry;
152 }
153
154 /* Check if there is a thread joining this one: */
155 if (curthread->joiner != NULL) {
156 pthread = curthread->joiner;
143 /* Check if there is a thread joining this one: */
144 if (curthread->joiner != NULL) {
145 pthread = curthread->joiner;
157 UMTX_LOCK(&pthread->lock);
158 curthread->joiner = NULL;
159
146 curthread->joiner = NULL;
147
160 /* Make the joining thread runnable: */
161 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
162
163 /* Set the return value for the joining thread: */
164 pthread->join_status.ret = curthread->ret;
165 pthread->join_status.error = 0;
166 pthread->join_status.thread = NULL;
148 /* Set the return value for the joining thread: */
149 pthread->join_status.ret = curthread->ret;
150 pthread->join_status.error = 0;
151 pthread->join_status.thread = NULL;
167 UMTX_UNLOCK(&pthread->lock);
168
152
169 /* Make this thread collectable by the garbage collector. */
170 PTHREAD_ASSERT(((curthread->attr.flags & PTHREAD_DETACHED) ==
171 0), "Cannot join a detached thread");
153 /* Make the joining thread runnable: */
154 PTHREAD_WAKE(pthread);
155
172 curthread->attr.flags |= PTHREAD_DETACHED;
173 }
174
175 /*
176 * Free any memory allocated for dead threads.
177 * Add this thread to the list of dead threads, and
178 * also remove it from the active threads list.
179 */
180 deadlist_free_threads();
181 TAILQ_INSERT_HEAD(&_dead_list, curthread, dle);
182 TAILQ_REMOVE(&_thread_list, curthread, tle);
156 curthread->attr.flags |= PTHREAD_DETACHED;
157 }
158
159 /*
160 * Free any memory allocated for dead threads.
161 * Add this thread to the list of dead threads, and
162 * also remove it from the active threads list.
163 */
164 deadlist_free_threads();
165 TAILQ_INSERT_HEAD(&_dead_list, curthread, dle);
166 TAILQ_REMOVE(&_thread_list, curthread, tle);
183 PTHREAD_SET_STATE(curthread, PS_DEAD);
184 _thread_critical_exit(curthread);
167 curthread->isdead = 1;
185
186 /* If we're the last thread, call it quits */
187 if (TAILQ_EMPTY(&_thread_list))
188 exitNow = 1;
189
190 THREAD_LIST_UNLOCK;
191 DEAD_LIST_UNLOCK;
192

--- 46 unchanged lines hidden ---
168
169 /* If we're the last thread, call it quits */
170 if (TAILQ_EMPTY(&_thread_list))
171 exitNow = 1;
172
173 THREAD_LIST_UNLOCK;
174 DEAD_LIST_UNLOCK;
175

--- 46 unchanged lines hidden ---