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