Merge from vendor branch READLINE:
[dragonfly.git] / lib / libc_r / uthread / uthread_gc.c
1 /*
2  * Copyright (c) 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: src/lib/libc_r/uthread/uthread_gc.c,v 1.11.2.5 2002/10/22 14:44:03 fjoe Exp $
33  * $DragonFly: src/lib/libc_r/uthread/uthread_gc.c,v 1.2 2003/06/17 04:26:48 dillon Exp $
34  *
35  * Garbage collector thread. Frees memory allocated for dead threads.
36  *
37  */
38 #include <errno.h>
39 #include <time.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/types.h>
44 #include <sys/mman.h>
45 #include <pthread.h>
46 #include "pthread_private.h"
47
48 pthread_addr_t
49 _thread_gc(pthread_addr_t arg)
50 {
51         struct pthread  *curthread = _get_curthread();
52         int             f_debug;
53         int             f_done = 0;
54         int             ret;
55         sigset_t        mask;
56         pthread_t       pthread;
57         pthread_t       pthread_cln;
58         struct timespec abstime;
59         void            *p_stack;
60
61         /* Block all signals */
62         sigfillset(&mask);
63         pthread_sigmask(SIG_BLOCK, &mask, NULL);
64
65         /* Mark this thread as a library thread (not a user thread). */
66         curthread->flags |= PTHREAD_FLAGS_PRIVATE;
67
68         /* Set a debug flag based on an environment variable. */
69         f_debug = (getenv("LIBC_R_DEBUG") != NULL);
70
71         /* Set the name of this thread. */
72         pthread_set_name_np(curthread,"GC");
73
74         while (!f_done) {
75                 /* Check if debugging this application. */
76                 if (f_debug)
77                         /* Dump thread info to file. */
78                         _thread_dump_info();
79
80                 /*
81                  * Defer signals to protect the scheduling queues from
82                  * access by the signal handler:
83                  */
84                 _thread_kern_sig_defer();
85
86                 /* Check if this is the last running thread: */
87                 if (TAILQ_FIRST(&_thread_list) == curthread &&
88                     TAILQ_NEXT(curthread, tle) == NULL)
89                         /*
90                          * This is the last thread, so it can exit
91                          * now.
92                          */
93                         f_done = 1;
94
95                 /*
96                  * Undefer and handle pending signals, yielding if
97                  * necessary:
98                  */
99                 _thread_kern_sig_undefer();
100
101                 /*
102                  * Lock the garbage collector mutex which ensures that
103                  * this thread sees another thread exit:
104                  */
105                 if (pthread_mutex_lock(&_gc_mutex) != 0)
106                         PANIC("Cannot lock gc mutex");
107
108                 /* No stack of thread structure to free yet: */
109                 p_stack = NULL;
110                 pthread_cln = NULL;
111
112                 /*
113                  * Enter a loop to search for the first dead thread that
114                  * has memory to free.
115                  */
116                 for (pthread = TAILQ_FIRST(&_dead_list);
117                      p_stack == NULL && pthread_cln == NULL && pthread != NULL;
118                      pthread = TAILQ_NEXT(pthread, dle)) {
119                         /* Check if the initial thread: */
120                         if (pthread == _thread_initial) {
121                                 /* Don't destroy the initial thread. */
122                         }
123                         /*
124                          * Check if this thread has detached:
125                          */
126                         else if ((pthread->attr.flags &
127                             PTHREAD_DETACHED) != 0) {
128                                 /* Remove this thread from the dead list: */
129                                 TAILQ_REMOVE(&_dead_list, pthread, dle);
130
131                                 /*
132                                  * Check if the stack was not specified by
133                                  * the caller to pthread_create() and has not
134                                  * been destroyed yet: 
135                                  */
136                                 if (pthread->attr.stackaddr_attr == NULL &&
137                                     pthread->stack != NULL) {
138                                         if (pthread->attr.stacksize_attr
139                                             == PTHREAD_STACK_DEFAULT) {
140                                                 /*
141                                                  * Default-size stack.  Cache
142                                                  * it:
143                                                  */
144                                                 struct stack    *spare_stack;
145
146                                                 spare_stack
147                                                     = (pthread->stack
148                                                        + PTHREAD_STACK_DEFAULT
149                                                        - sizeof(struct stack));
150                                                 SLIST_INSERT_HEAD(&_stackq,
151                                                                   spare_stack,
152                                                                   qe);
153                                         } else {
154                                                 /*
155                                                  * Non-standard stack size.
156                                                  * free() it outside the locks.
157                                                  */
158                                                 p_stack = pthread->stack;
159                                         }
160                                 }
161
162                                 /*
163                                  * Point to the thread structure that must
164                                  * be freed outside the locks:
165                                  */
166                                 pthread_cln = pthread;
167
168                         } else {
169                                 /*
170                                  * This thread has not detached, so do
171                                  * not destroy it.
172                                  *
173                                  * Check if the stack was not specified by
174                                  * the caller to pthread_create() and has not
175                                  * been destroyed yet: 
176                                  */
177                                 if (pthread->attr.stackaddr_attr == NULL &&
178                                     pthread->stack != NULL) {
179                                         if (pthread->attr.stacksize_attr
180                                             == PTHREAD_STACK_DEFAULT) {
181                                                 /*
182                                                  * Default-size stack.  Cache
183                                                  * it:
184                                                  */
185                                                 struct stack    *spare_stack;
186
187                                                 spare_stack
188                                                     = (pthread->stack
189                                                        + PTHREAD_STACK_DEFAULT
190                                                        - sizeof(struct stack));
191                                                 SLIST_INSERT_HEAD(&_stackq,
192                                                                   spare_stack,
193                                                                   qe);
194                                         } else {
195                                                 /*
196                                                  * Non-standard stack size.
197                                                  * free() it outside the locks:
198                                                  */
199                                                 p_stack = pthread->stack;
200                                         }
201                                         
202                                         /*
203                                          * NULL the stack pointer now
204                                          * that the memory has been freed: 
205                                          */
206                                         pthread->stack = NULL;
207                                 }
208                         }
209                 }
210
211                 /*
212                  * Check if this is not the last thread and there is no
213                  * memory to free this time around.
214                  */
215                 if (!f_done && p_stack == NULL && pthread_cln == NULL) {
216                         /* Get the current time. */
217                         if (clock_gettime(CLOCK_REALTIME,&abstime) != 0)
218                                 PANIC("gc cannot get time");
219
220                         /*
221                          * Do a backup poll in 10 seconds if no threads
222                          * die before then.
223                          */
224                         abstime.tv_sec += 10;
225
226                         /*
227                          * Wait for a signal from a dying thread or a
228                          * timeout (for a backup poll).
229                          */
230                         if ((ret = pthread_cond_timedwait(&_gc_cond,
231                             &_gc_mutex, &abstime)) != 0 && ret != ETIMEDOUT)
232                                 PANIC("gc cannot wait for a signal");
233                 }
234
235                 /* Unlock the garbage collector mutex: */
236                 if (pthread_mutex_unlock(&_gc_mutex) != 0)
237                         PANIC("Cannot unlock gc mutex");
238
239                 /*
240                  * If there is memory to free, do it now. The call to
241                  * free() might block, so this must be done outside the
242                  * locks.
243                  */
244                 if (p_stack != NULL)
245                         free(p_stack);
246                 if (pthread_cln != NULL) {
247                         if (pthread_cln->name != NULL) {
248                                 /* Free the thread name string. */
249                                 free(pthread_cln->name);
250                         }
251                         /*
252                          * Free the memory allocated for the thread
253                          * structure.
254                          */
255                         free(pthread_cln);
256                 }
257         }
258         return (NULL);
259 }