thr_kern.c revision 33292
1/*
2 * Copyright (c) 1995 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 REGENTS 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 * $Id: uthread_kern.c,v 1.5 1997/04/01 22:51:48 jb Exp $
33 *
34 */
35#include <errno.h>
36#include <stdlib.h>
37#include <stdarg.h>
38#include <string.h>
39#include <unistd.h>
40#include <setjmp.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <sys/time.h>
44#include <sys/socket.h>
45#include <sys/uio.h>
46#include <sys/syscall.h>
47#include <fcntl.h>
48#ifdef _THREAD_SAFE
49#include <pthread.h>
50#include "pthread_private.h"
51
52/* Static variables: */
53static sigset_t sig_to_block = 0xffffffff;
54static sigset_t sig_to_unblock = 0;
55
56/* Static function prototype definitions: */
57static void
58_thread_kern_select(int wait_reqd);
59static void
60_thread_signal(pthread_t pthread, int sig);
61
62void
63_thread_kern_sched(struct sigcontext * scp)
64{
65#ifndef	__alpha
66	char           *fdata;
67#endif
68	int             i;
69	int             prio = -1;
70	pthread_t       pthread;
71	pthread_t       pthread_h = NULL;
72	pthread_t       pthread_nxt = NULL;
73	pthread_t       pthread_prv = NULL;
74	pthread_t       pthread_s = NULL;
75	struct itimerval itimer;
76	struct timespec ts;
77	struct timespec ts1;
78	struct timeval  tv;
79	struct timeval  tv1;
80
81	/* Block signals: */
82	_thread_kern_sig_block(NULL);
83
84	/* Check if this function was called from the signal handler: */
85	if (scp != NULL) {
86		/*
87		 * Copy the signal context to the current thread's jump
88		 * buffer:
89		 */
90		memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext));
91
92#ifndef	__alpha
93		/* Point to the floating point data in the running thread: */
94		fdata = _thread_run->saved_fp;
95
96		/* Save the floating point data: */
97__asm__("fnsave %0": :"m"(*fdata));
98#endif
99
100		/* Flag the signal context as the last state saved: */
101		_thread_run->sig_saved = 1;
102	}
103	/* Save the state of the current thread: */
104	else if (_thread_sys_setjmp(_thread_run->saved_jmp_buf) != 0) {
105		/* Unblock signals (just in case): */
106		_thread_kern_sig_unblock(0);
107
108		/*
109		 * This point is reached when a longjmp() is called to
110		 * restore the state of a thread.
111		 */
112		return;
113	} else {
114		/* Flag the jump buffer was the last state saved: */
115		_thread_run->sig_saved = 0;
116	}
117
118	/* Point to the first dead thread (if there are any): */
119	pthread = _thread_dead;
120
121	/* There is no previous dead thread: */
122	pthread_prv = NULL;
123
124	/* Enter a loop to cleanup after dead threads: */
125	while (pthread != NULL) {
126		/* Save a pointer to the next thread: */
127		pthread_nxt = pthread->nxt;
128
129		/* Check if this thread is one which is running: */
130		if (pthread == _thread_run || pthread == _thread_initial) {
131			/*
132			 * Don't destroy the running thread or the initial
133			 * thread.
134			 */
135			pthread_prv = pthread;
136		}
137		/*
138		 * Check if this thread has detached or if it is a signal
139		 * handler thread:
140		 */
141		else if (((pthread->attr.flags & PTHREAD_DETACHED) != 0) || pthread->parent_thread != NULL) {
142			/* Check if there is no previous dead thread: */
143			if (pthread_prv == NULL) {
144				/*
145				 * The dead thread is at the head of the
146				 * list:
147				 */
148				_thread_dead = pthread_nxt;
149			} else {
150				/*
151				 * The dead thread is not at the head of the
152				 * list:
153				 */
154				pthread_prv->nxt = pthread->nxt;
155			}
156
157			/*
158			 * Check if the stack was not specified by the caller
159			 * to pthread_create and has not been destroyed yet:
160			 */
161			if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
162				/* Free the stack of the dead thread: */
163				free(pthread->stack);
164			}
165			/* Free the memory allocated to the thread structure: */
166			free(pthread);
167		} else {
168			/*
169			 * This thread has not detached, so do not destroy
170			 * it:
171			 */
172			pthread_prv = pthread;
173
174			/*
175			 * Check if the stack was not specified by the caller
176			 * to pthread_create and has not been destroyed yet:
177			 */
178			if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
179				/* Free the stack of the dead thread: */
180				free(pthread->stack);
181
182				/*
183				 * NULL the stack pointer now that the memory
184				 * has been freed:
185				 */
186				pthread->stack = NULL;
187			}
188		}
189
190		/* Point to the next thread: */
191		pthread = pthread_nxt;
192	}
193
194	/*
195	 * Enter a the scheduling loop that finds the next thread that is
196	 * ready to run. This loop completes when there are no more threads
197	 * in the global list or when a thread has its state restored by
198	 * either a sigreturn (if the state was saved as a sigcontext) or a
199	 * longjmp (if the state was saved by a setjmp).
200	 */
201	while (_thread_link_list != NULL) {
202		/* Get the current time of day: */
203		gettimeofday(&tv, NULL);
204		TIMEVAL_TO_TIMESPEC(&tv, &ts);
205
206		/*
207		 * Poll file descriptors to update the state of threads
208		 * waiting on file I/O where data may be available:
209		 */
210		_thread_kern_select(0);
211
212		/*
213		 * Enter a loop to look for sleeping threads that are ready
214		 * or threads with pending signals that are no longer
215		 * blocked:
216		 */
217		for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
218			/* Enter a loop to process the sending signals: */
219			for (i = 1; i < NSIG; i++) {
220				/*
221				 * Check if there are no pending signals of
222				 * this type:
223				 */
224				if (pthread->sigpend[i] == 0) {
225				}
226				/* Check if this signal type is not masked: */
227				else if (sigismember(&pthread->sigmask, i) == 0) {
228					/*
229					 * Delete the signal from the set of
230					 * pending signals for this thread:
231					 */
232					pthread->sigpend[i] -= 1;
233
234					/*
235					 * Act on the signal for the current
236					 * thread:
237					 */
238					_thread_signal(pthread, i);
239				} else {
240					/*
241					 * This signal is masked, so make
242					 * sure the count does not exceed 1:
243					 */
244					pthread->sigpend[i] = 1;
245				}
246			}
247
248			/* Check if this thread is to timeout: */
249			if (pthread->state == PS_COND_WAIT ||
250			    pthread->state == PS_SLEEP_WAIT ||
251			    pthread->state == PS_FDR_WAIT ||
252			    pthread->state == PS_FDW_WAIT ||
253			    pthread->state == PS_SELECT_WAIT) {
254				/* Check if this thread is to wait forever: */
255				if (pthread->wakeup_time.tv_sec == -1) {
256				}
257				/*
258				 * Check if this thread is to wakeup
259				 * immediately or if it is past its wakeup
260				 * time:
261				 */
262				else if ((pthread->wakeup_time.tv_sec == 0 &&
263					pthread->wakeup_time.tv_nsec == 0) ||
264					 (ts.tv_sec > pthread->wakeup_time.tv_sec) ||
265					 ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
266					  (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
267					/*
268					 * Check if this thread is waiting on
269					 * select:
270					 */
271					if (pthread->state == PS_SELECT_WAIT) {
272						/*
273						 * The select has timed out,
274						 * so zero the file
275						 * descriptor sets:
276						 */
277						FD_ZERO(&pthread->data.select_data->readfds);
278						FD_ZERO(&pthread->data.select_data->writefds);
279						FD_ZERO(&pthread->data.select_data->exceptfds);
280						pthread->data.select_data->nfds = 0;
281					}
282					/*
283					 * Return an error as an interrupted
284					 * wait:
285					 */
286					_thread_seterrno(pthread, EINTR);
287
288					/*
289					 * Flag the timeout in the thread
290					 * structure:
291					 */
292					pthread->timeout = 1;
293
294					/*
295					 * Change the threads state to allow
296					 * it to be restarted:
297					 */
298					PTHREAD_NEW_STATE(pthread,PS_RUNNING);
299				}
300			}
301		}
302
303		/* Check if there is a current thread: */
304		if (_thread_run != &_thread_kern_thread) {
305			/*
306			 * Save the current time as the time that the thread
307			 * became inactive:
308			 */
309			_thread_run->last_inactive.tv_sec = tv.tv_sec;
310			_thread_run->last_inactive.tv_usec = tv.tv_usec;
311
312			/*
313			 * Accumulate the number of microseconds that this
314			 * thread has run for:
315			 */
316			_thread_run->slice_usec += (_thread_run->last_inactive.tv_sec -
317				_thread_run->last_active.tv_sec) * 1000000 +
318				_thread_run->last_inactive.tv_usec -
319				_thread_run->last_active.tv_usec;
320
321			/*
322			 * Check if this thread has reached its allocated
323			 * time slice period:
324			 */
325			if (_thread_run->slice_usec > TIMESLICE_USEC) {
326				/*
327				 * Flag the allocated time slice period as
328				 * up:
329				 */
330				_thread_run->slice_usec = -1;
331			}
332		}
333		/* Check if an incremental priority update is required: */
334		if (((tv.tv_sec - kern_inc_prio_time.tv_sec) * 1000000 +
335		 tv.tv_usec - kern_inc_prio_time.tv_usec) > INC_PRIO_USEC) {
336			/*
337			 * Enter a loop to look for run-enabled threads that
338			 * have not run since the last time that an
339			 * incremental priority update was performed:
340			 */
341			for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
342				/* Check if this thread is unable to run: */
343				if (pthread->state != PS_RUNNING) {
344				}
345				/*
346				 * Check if the last time that this thread
347				 * was run (as indicated by the last time it
348				 * became inactive) is before the time that
349				 * the last incremental priority check was
350				 * made:
351				 */
352				else if (timercmp(&_thread_run->last_inactive, &kern_inc_prio_time, >)) {
353					/*
354					 * Increment the incremental priority
355					 * for this thread in the hope that
356					 * it will eventually get a chance to
357					 * run:
358					 */
359					(pthread->inc_prio)++;
360				}
361			}
362
363			/* Save the new incremental priority update time: */
364			kern_inc_prio_time.tv_sec = tv.tv_sec;
365			kern_inc_prio_time.tv_usec = tv.tv_usec;
366		}
367		/*
368		 * Enter a loop to look for the first thread of the highest
369		 * priority that is ready to run:
370		 */
371		for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
372			/* Check if in single-threaded mode: */
373			if (_thread_single != NULL) {
374				/*
375				 * Check if the current thread is
376				 * the thread for which single-threaded
377				 * mode is enabled:
378				 */
379				if (pthread == _thread_single) {
380					/*
381					 * This thread is allowed
382					 * to run.
383					 */
384				} else {
385					/*
386					 * Walk up the signal handler
387                                         * parent thread tree to see
388					 * if the current thread is
389					 * descended from the thread
390					 * for which single-threaded
391					 * mode is enabled.
392					 */
393					pthread_nxt = pthread;
394					while(pthread_nxt != NULL &&
395						pthread_nxt != _thread_single) {
396						pthread_nxt = pthread->parent_thread;
397					}
398					/*
399					 * Check if the current
400					 * thread is not descended
401					 * from the thread for which
402					 * single-threaded mode is
403					 * enabled.
404					 */
405					if (pthread_nxt == NULL)
406						/* Ignore this thread. */
407						continue;
408				}
409			}
410
411			/* Check if the current thread is unable to run: */
412			if (pthread->state != PS_RUNNING) {
413			}
414			/*
415			 * Check if no run-enabled thread has been seen or if
416			 * the current thread has a priority higher than the
417			 * highest seen so far:
418			 */
419			else if (pthread_h == NULL || (pthread->pthread_priority + pthread->inc_prio) > prio) {
420				/*
421				 * Save this thread as the highest priority
422				 * thread seen so far:
423				 */
424				pthread_h = pthread;
425				prio = pthread->pthread_priority + pthread->inc_prio;
426			}
427		}
428
429		/*
430		 * Enter a loop to look for a thread that: 1. Is run-enabled.
431		 * 2. Has the required agregate priority. 3. Has not been
432		 * allocated its allocated time slice. 4. Became inactive
433		 * least recently.
434		 */
435		for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
436			/* Check if in single-threaded mode: */
437			if (_thread_single != NULL) {
438				/*
439				 * Check if the current thread is
440				 * the thread for which single-threaded
441				 * mode is enabled:
442				 */
443				if (pthread == _thread_single) {
444					/*
445					 * This thread is allowed
446					 * to run.
447					 */
448				} else {
449					/*
450					 * Walk up the signal handler
451                                         * parent thread tree to see
452					 * if the current thread is
453					 * descended from the thread
454					 * for which single-threaded
455					 * mode is enabled.
456					 */
457					pthread_nxt = pthread;
458					while(pthread_nxt != NULL &&
459						pthread_nxt != _thread_single) {
460						pthread_nxt = pthread->parent_thread;
461					}
462					/*
463					 * Check if the current
464					 * thread is not descended
465					 * from the thread for which
466					 * single-threaded mode is
467					 * enabled.
468					 */
469					if (pthread_nxt == NULL)
470						/* Ignore this thread. */
471						continue;
472				}
473			}
474
475			/* Check if the current thread is unable to run: */
476			if (pthread->state != PS_RUNNING) {
477				/* Ignore threads that are not ready to run. */
478			}
479			/*
480			 * Check if the current thread as an agregate
481			 * priority not equal to the highest priority found
482			 * above:
483			 */
484			else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
485				/*
486				 * Ignore threads which have lower agregate
487				 * priority.
488				 */
489			}
490			/*
491			 * Check if the current thread reached its time slice
492			 * allocation last time it ran (or if it has not run
493			 * yet):
494			 */
495			else if (pthread->slice_usec == -1) {
496			}
497			/*
498			 * Check if an eligible thread has not been found
499			 * yet, or if the current thread has an inactive time
500			 * earlier than the last one seen:
501			 */
502			else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
503				/*
504				 * Save the pointer to the current thread as
505				 * the most eligible thread seen so far:
506				 */
507				pthread_s = pthread;
508
509				/*
510				 * Save the time that the selected thread
511				 * became inactive:
512				 */
513				tv1.tv_sec = pthread->last_inactive.tv_sec;
514				tv1.tv_usec = pthread->last_inactive.tv_usec;
515			}
516		}
517
518		/*
519		 * Check if no thread was selected according to incomplete
520		 * time slice allocation:
521		 */
522		if (pthread_s == NULL) {
523			/*
524			 * Enter a loop to look for any other thread that: 1.
525			 * Is run-enabled. 2. Has the required agregate
526			 * priority. 3. Became inactive least recently.
527			 */
528			for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
529				/* Check if in single-threaded mode: */
530				if (_thread_single != NULL) {
531					/*
532					 * Check if the current thread is
533					 * the thread for which single-threaded
534					 * mode is enabled:
535					 */
536					if (pthread == _thread_single) {
537						/*
538						 * This thread is allowed
539						 * to run.
540						 */
541					} else {
542						/*
543						 * Walk up the signal handler
544						 * parent thread tree to see
545						 * if the current thread is
546						 * descended from the thread
547						 * for which single-threaded
548						 * mode is enabled.
549						 */
550						pthread_nxt = pthread;
551						while(pthread_nxt != NULL &&
552							pthread_nxt != _thread_single) {
553							pthread_nxt = pthread->parent_thread;
554						}
555						/*
556						 * Check if the current
557						 * thread is not descended
558						 * from the thread for which
559						 * single-threaded mode is
560						 * enabled.
561						 */
562						if (pthread_nxt == NULL)
563							/* Ignore this thread. */
564							continue;
565					}
566				}
567
568				/*
569				 * Check if the current thread is unable to
570				 * run:
571				 */
572				if (pthread->state != PS_RUNNING) {
573					/*
574					 * Ignore threads that are not ready
575					 * to run.
576					 */
577				}
578				/*
579				 * Check if the current thread as an agregate
580				 * priority not equal to the highest priority
581				 * found above:
582				 */
583				else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
584					/*
585					 * Ignore threads which have lower
586					 * agregate priority.
587					 */
588				}
589				/*
590				 * Check if an eligible thread has not been
591				 * found yet, or if the current thread has an
592				 * inactive time earlier than the last one
593				 * seen:
594				 */
595				else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
596					/*
597					 * Save the pointer to the current
598					 * thread as the most eligible thread
599					 * seen so far:
600					 */
601					pthread_s = pthread;
602
603					/*
604					 * Save the time that the selected
605					 * thread became inactive:
606					 */
607					tv1.tv_sec = pthread->last_inactive.tv_sec;
608					tv1.tv_usec = pthread->last_inactive.tv_usec;
609				}
610			}
611		}
612		/* Check if there are no threads ready to run: */
613		if (pthread_s == NULL) {
614			/*
615			 * Lock the pthread kernel by changing the pointer to
616			 * the running thread to point to the global kernel
617			 * thread structure:
618			 */
619			_thread_run = &_thread_kern_thread;
620
621			/*
622			 * There are no threads ready to run, so wait until
623			 * something happens that changes this condition:
624			 */
625			_thread_kern_select(1);
626		} else {
627			/* Make the selected thread the current thread: */
628			_thread_run = pthread_s;
629
630			/*
631			 * Save the current time as the time that the thread
632			 * became active:
633			 */
634			_thread_run->last_active.tv_sec = tv.tv_sec;
635			_thread_run->last_active.tv_usec = tv.tv_usec;
636
637			/*
638			 * Check if this thread is running for the first time
639			 * or running again after using its full time slice
640			 * allocation:
641			 */
642			if (_thread_run->slice_usec == -1) {
643				/* Reset the accumulated time slice period: */
644				_thread_run->slice_usec = 0;
645			}
646			/*
647			 * Reset the incremental priority now that this
648			 * thread has been given the chance to run:
649			 */
650			_thread_run->inc_prio = 0;
651
652			/* Check if there is more than one thread: */
653			if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) {
654				/*
655				 * Define the maximum time before a SIGVTALRM
656				 * is required:
657				 */
658				itimer.it_value.tv_sec = 0;
659				itimer.it_value.tv_usec = TIMESLICE_USEC;
660
661				/*
662				 * The interval timer is not reloaded when it
663				 * times out. The interval time needs to be
664				 * calculated every time.
665				 */
666				itimer.it_interval.tv_sec = 0;
667				itimer.it_interval.tv_usec = 0;
668
669				/*
670				 * Enter a loop to look for threads waiting
671				 * for a time:
672				 */
673				for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
674					/*
675					 * Check if this thread is to
676					 * timeout:
677					 */
678					if (pthread->state == PS_COND_WAIT ||
679					  pthread->state == PS_SLEEP_WAIT ||
680					    pthread->state == PS_FDR_WAIT ||
681					    pthread->state == PS_FDW_WAIT ||
682					 pthread->state == PS_SELECT_WAIT) {
683						/*
684						 * Check if this thread is to
685						 * wait forever:
686						 */
687						if (pthread->wakeup_time.tv_sec == -1) {
688						}
689						/*
690						 * Check if this thread is to
691						 * wakeup immediately:
692						 */
693						else if (pthread->wakeup_time.tv_sec == 0 &&
694							 pthread->wakeup_time.tv_nsec == 0) {
695						}
696						/*
697						 * Check if the current time
698						 * is after the wakeup time:
699						 */
700						else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
701							 ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
702							  (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
703						} else {
704							/*
705							 * Calculate the time
706							 * until this thread
707							 * is ready, allowing
708							 * for the clock
709							 * resolution:
710							 */
711							ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
712							ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
713								CLOCK_RES_NSEC;
714
715							/*
716							 * Check for
717							 * underflow of the
718							 * nanosecond field:
719							 */
720							if (ts1.tv_nsec < 0) {
721								/*
722								 * Allow for
723								 * the
724								 * underflow
725								 * of the
726								 * nanosecond
727								 * field:
728								 */
729								ts1.tv_sec--;
730								ts1.tv_nsec += 1000000000;
731							}
732							/*
733							 * Check for overflow
734							 * of the nanosecond
735							 * field:
736							 */
737							if (ts1.tv_nsec >= 1000000000) {
738								/*
739								 * Allow for
740								 * the
741								 * overflow
742								 * of the
743								 * nanosecond
744								 * field:
745								 */
746								ts1.tv_sec++;
747								ts1.tv_nsec -= 1000000000;
748							}
749							/*
750							 * Convert the
751							 * timespec structure
752							 * to a timeval
753							 * structure:
754							 */
755							TIMESPEC_TO_TIMEVAL(&tv, &ts1);
756
757							/*
758							 * Check if the
759							 * thread will be
760							 * ready sooner than
761							 * the earliest one
762							 * found so far:
763							 */
764							if (timercmp(&tv, &itimer.it_value, <)) {
765								/*
766								 * Update the
767								 * time
768								 * value:
769								 */
770								itimer.it_value.tv_sec = tv.tv_sec;
771								itimer.it_value.tv_usec = tv.tv_usec;
772							}
773						}
774					}
775				}
776
777				/*
778				 * Start the interval timer for the
779				 * calculated time interval:
780				 */
781				if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) != 0) {
782					/*
783					 * Cannot initialise the timer, so
784					 * abort this process:
785					 */
786					PANIC("Cannot set virtual timer");
787				}
788			}
789			/* Check if a signal context was saved: */
790			if (_thread_run->sig_saved == 1) {
791#ifndef	__alpha
792				/*
793				 * Point to the floating point data in the
794				 * running thread:
795				 */
796				fdata = _thread_run->saved_fp;
797
798				/* Restore the floating point state: */
799		__asm__("frstor %0": :"m"(*fdata));
800#endif
801
802				/*
803				 * Do a sigreturn to restart the thread that
804				 * was interrupted by a signal:
805				 */
806				_thread_sys_sigreturn(&_thread_run->saved_sigcontext);
807			} else {
808				/*
809				 * Do a longjmp to restart the thread that
810				 * was context switched out (by a longjmp to
811				 * a different thread):
812				 */
813				_thread_sys_longjmp(_thread_run->saved_jmp_buf, 1);
814			}
815
816			/* This point should not be reached. */
817			PANIC("Thread has returned from sigreturn or longjmp");
818		}
819	}
820
821	/* There are no more threads, so exit this process: */
822	exit(0);
823}
824
825static void
826_thread_signal(pthread_t pthread, int sig)
827{
828	int		done;
829	long            l;
830	pthread_t       new_pthread;
831	struct sigaction act;
832	void           *arg;
833
834	/*
835	 * Assume that the signal will not be dealt with according
836	 * to the thread state:
837	 */
838	done = 0;
839
840	/* Process according to thread state: */
841	switch (pthread->state) {
842	/* States which do not change when a signal is trapped: */
843	case PS_COND_WAIT:
844	case PS_DEAD:
845	case PS_FDLR_WAIT:
846	case PS_FDLW_WAIT:
847	case PS_JOIN:
848	case PS_MUTEX_WAIT:
849	case PS_RUNNING:
850	case PS_STATE_MAX:
851	case PS_SIGTHREAD:
852	case PS_SUSPENDED:
853		/* Nothing to do here. */
854		break;
855
856	/* Wait for child: */
857	case PS_WAIT_WAIT:
858		/* Check if the signal is from a child exiting: */
859		if (sig == SIGCHLD) {
860			/* Reset the error: */
861			_thread_seterrno(pthread, 0);
862
863			/* Change the state of the thread to run: */
864			PTHREAD_NEW_STATE(pthread,PS_RUNNING);
865		} else {
866			/* Return the 'interrupted' error: */
867			_thread_seterrno(pthread, EINTR);
868
869			/* Change the state of the thread to run: */
870			PTHREAD_NEW_STATE(pthread,PS_RUNNING);
871		}
872		pthread->interrupted = 1;
873		break;
874
875	/* Waiting on I/O for zero or more file descriptors: */
876	case PS_SELECT_WAIT:
877		pthread->data.select_data->nfds = -1;
878
879		/* Return the 'interrupted' error: */
880		_thread_seterrno(pthread, EINTR);
881		pthread->interrupted = 1;
882
883		/* Change the state of the thread to run: */
884		PTHREAD_NEW_STATE(pthread,PS_RUNNING);
885		break;
886
887	/*
888	 * States that are interrupted by the occurrence of a signal
889	 * other than the scheduling alarm:
890	 */
891	case PS_FDR_WAIT:
892	case PS_FDW_WAIT:
893	case PS_SLEEP_WAIT:
894		/* Return the 'interrupted' error: */
895		_thread_seterrno(pthread, EINTR);
896		pthread->interrupted = 1;
897
898		/* Change the state of the thread to run: */
899		PTHREAD_NEW_STATE(pthread,PS_RUNNING);
900
901		/* Return the signal number: */
902		pthread->signo = sig;
903		break;
904
905	/* Waiting on a signal: */
906	case PS_SIGWAIT:
907		/* Change the state of the thread to run: */
908		PTHREAD_NEW_STATE(pthread,PS_RUNNING);
909
910		/* Return the signal number: */
911		pthread->signo = sig;
912
913		/* Flag the signal as dealt with: */
914		done = 1;
915		break;
916	}
917
918	/*
919	 * Check if this signal has been dealt with, or is being
920	 * ignored:
921	 */
922	if (done || pthread->act[sig - 1].sa_handler == SIG_IGN) {
923		/* Ignore the signal for this thread. */
924	}
925	/* Check if this signal is to use the default handler: */
926	else if (pthread->act[sig - 1].sa_handler == SIG_DFL) {
927		/* Process according to signal type: */
928		switch (sig) {
929		/* Signals which cause core dumps: */
930		case SIGQUIT:
931		case SIGILL:
932		case SIGTRAP:
933		case SIGABRT:
934		case SIGEMT:
935		case SIGFPE:
936		case SIGBUS:
937		case SIGSEGV:
938		case SIGSYS:
939			/* Clear the signal action: */
940			sigfillset(&act.sa_mask);
941			act.sa_handler = SIG_DFL;
942			act.sa_flags = SA_RESTART;
943			_thread_sys_sigaction(sig, &act, NULL);
944
945			/*
946			 * Do a sigreturn back to where the signal was
947			 * detected and a core dump should occur:
948			 */
949			_thread_sys_sigreturn(&pthread->saved_sigcontext);
950			break;
951
952		/*
953		 * The following signals should terminate the
954		 * process. Do this by clearing the signal action
955		 * and then re-throwing the signal.
956		 */
957		case SIGHUP:
958		case SIGINT:
959		case SIGPIPE:
960		case SIGALRM:
961		case SIGTERM:
962		case SIGXCPU:
963		case SIGXFSZ:
964		case SIGVTALRM:
965		case SIGUSR1:
966		case SIGUSR2:
967		/* These signals stop the process. Also re-throw them. */
968		case SIGTSTP:
969		case SIGTTIN:
970		case SIGTTOU:
971                        /* Clear the signal action: */
972                        sigfillset(&act.sa_mask);
973                        act.sa_handler = SIG_DFL;
974                        act.sa_flags = SA_RESTART;
975                        _thread_sys_sigaction(sig, &act, NULL);
976			/* Re-throw to ourselves. */
977                        kill(getpid(), sig);
978			break;
979
980		case SIGCONT:
981			/*
982			 * If we get this it means that we were
983			 * probably stopped and then continued.
984			 * Reset the handler for the SIGTSTP, SIGTTIN
985			 * and SIGTTOU signals.
986			 */
987
988                	sigfillset(&act.sa_mask);
989	                act.sa_handler = (void (*) ()) _thread_sig_handler;
990			act.sa_flags = SA_RESTART;
991
992                        /* Initialise the signals for default handling: */
993                        if (_thread_sys_sigaction(SIGTSTP, &act, NULL) != 0) {
994                                PANIC("Cannot initialise SIGTSTP signal handler");
995                        }
996                        if (_thread_sys_sigaction(SIGTTIN, &act, NULL) != 0) {
997                                PANIC("Cannot initialise SIGTTIN signal handler");
998                        }
999                        if (_thread_sys_sigaction(SIGTTOU, &act, NULL) != 0) {
1000                                PANIC("Cannot initialise SIGTTOU signal handler");
1001                        }
1002			break;
1003
1004		/* Default processing for other signals: */
1005		default:
1006			/*
1007			 * ### Default processing is a problem to resolve!
1008			 * ###
1009			 */
1010			break;
1011		}
1012	} else {
1013		/*
1014		 * Cast the signal number as a long and then to a void
1015		 * pointer. Sigh. This is POSIX.
1016		 */
1017		l = (long) sig;
1018		arg = (void *) l;
1019
1020		/* Create a signal handler thread, but don't run it yet: */
1021		if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
1022			/*
1023			 * Error creating signal handler thread, so abort
1024			 * this process:
1025			 */
1026			PANIC("Cannot create signal handler thread");
1027		}
1028	}
1029
1030	/* Nothing to return. */
1031	return;
1032}
1033
1034void
1035_thread_kern_sig_block(int *status)
1036{
1037	sigset_t        oset;
1038
1039	/*
1040	 * Block all signals so that the process will not be interrupted by
1041	 * signals:
1042	 */
1043	_thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
1044
1045	/* Check if the caller wants the current block status returned: */
1046	if (status != NULL) {
1047		/* Return the previous signal block status: */
1048		*status = (oset != 0);
1049	}
1050	return;
1051}
1052
1053void
1054_thread_kern_sig_unblock(int status)
1055{
1056	sigset_t        oset;
1057
1058	/*
1059	 * Check if the caller thinks that signals weren't blocked when it
1060	 * called _thread_kern_sig_block:
1061	 */
1062	if (status == 0) {
1063		/*
1064		 * Unblock all signals so that the process will be
1065		 * interrupted when a signal occurs:
1066		 */
1067		_thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
1068	}
1069	return;
1070}
1071
1072void
1073_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
1074{
1075	/* Change the state of the current thread: */
1076	_thread_run->state = state;
1077	_thread_run->fname = fname;
1078	_thread_run->lineno = lineno;
1079
1080	/* Schedule the next thread that is ready: */
1081	_thread_kern_sched(NULL);
1082	return;
1083}
1084
1085static void
1086_thread_kern_select(int wait_reqd)
1087{
1088	char            bufr[128];
1089	fd_set          fd_set_except;
1090	fd_set          fd_set_read;
1091	fd_set          fd_set_write;
1092	int             count = 0;
1093	int             count_dec;
1094	int             found_one;
1095	int             i;
1096	int             nfds = -1;
1097	int             settimeout;
1098	pthread_t       pthread;
1099	ssize_t         num;
1100	struct timespec ts;
1101	struct timespec ts1;
1102	struct timeval *p_tv;
1103	struct timeval  tv;
1104	struct timeval  tv1;
1105
1106	/* Zero the file descriptor sets: */
1107	FD_ZERO(&fd_set_read);
1108	FD_ZERO(&fd_set_write);
1109	FD_ZERO(&fd_set_except);
1110
1111	/* Check if the caller wants to wait: */
1112	if (wait_reqd) {
1113		/*
1114		 * Add the pthread kernel pipe file descriptor to the read
1115		 * set:
1116		 */
1117		FD_SET(_thread_kern_pipe[0], &fd_set_read);
1118		nfds = _thread_kern_pipe[0];
1119
1120		/* Get the current time of day: */
1121		gettimeofday(&tv, NULL);
1122		TIMEVAL_TO_TIMESPEC(&tv, &ts);
1123	}
1124	/* Initialise the time value structure: */
1125	tv.tv_sec = 0;
1126	tv.tv_usec = 0;
1127
1128	/*
1129	 * Enter a loop to process threads waiting on either file descriptors
1130	 * or times:
1131	 */
1132	for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
1133		/* Assume that this state does not time out: */
1134		settimeout = 0;
1135
1136		/* Process according to thread state: */
1137		switch (pthread->state) {
1138		/*
1139		 * States which do not depend on file descriptor I/O
1140		 * operations or timeouts:
1141		 */
1142		case PS_DEAD:
1143		case PS_FDLR_WAIT:
1144		case PS_FDLW_WAIT:
1145		case PS_JOIN:
1146		case PS_MUTEX_WAIT:
1147		case PS_RUNNING:
1148		case PS_SIGTHREAD:
1149		case PS_SIGWAIT:
1150		case PS_STATE_MAX:
1151		case PS_WAIT_WAIT:
1152		case PS_SUSPENDED:
1153			/* Nothing to do here. */
1154			break;
1155
1156		/* File descriptor read wait: */
1157		case PS_FDR_WAIT:
1158			/* Add the file descriptor to the read set: */
1159			FD_SET(pthread->data.fd.fd, &fd_set_read);
1160
1161			/*
1162			 * Check if this file descriptor is greater than any
1163			 * of those seen so far:
1164			 */
1165			if (pthread->data.fd.fd > nfds) {
1166				/* Remember this file descriptor: */
1167				nfds = pthread->data.fd.fd;
1168			}
1169			/* Increment the file descriptor count: */
1170			count++;
1171
1172			/* This state can time out: */
1173			settimeout = 1;
1174			break;
1175
1176		/* File descriptor write wait: */
1177		case PS_FDW_WAIT:
1178			/* Add the file descriptor to the write set: */
1179			FD_SET(pthread->data.fd.fd, &fd_set_write);
1180
1181			/*
1182			 * Check if this file descriptor is greater than any
1183			 * of those seen so far:
1184			 */
1185			if (pthread->data.fd.fd > nfds) {
1186				/* Remember this file descriptor: */
1187				nfds = pthread->data.fd.fd;
1188			}
1189			/* Increment the file descriptor count: */
1190			count++;
1191
1192			/* This state can time out: */
1193			settimeout = 1;
1194			break;
1195
1196		/* States that time out: */
1197		case PS_SLEEP_WAIT:
1198		case PS_COND_WAIT:
1199			/* Flag a timeout as required: */
1200			settimeout = 1;
1201			break;
1202
1203		/* Select wait: */
1204		case PS_SELECT_WAIT:
1205			/*
1206			 * Enter a loop to process each file descriptor in
1207			 * the thread-specific file descriptor sets:
1208			 */
1209			for (i = 0; i < pthread->data.select_data->nfds; i++) {
1210				/*
1211				 * Check if this file descriptor is set for
1212				 * exceptions:
1213				 */
1214				if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
1215					/*
1216					 * Add the file descriptor to the
1217					 * exception set:
1218					 */
1219					FD_SET(i, &fd_set_except);
1220
1221					/*
1222					 * Increment the file descriptor
1223					 * count:
1224					 */
1225					count++;
1226
1227					/*
1228					 * Check if this file descriptor is
1229					 * greater than any of those seen so
1230					 * far:
1231					 */
1232					if (i > nfds) {
1233						/*
1234						 * Remember this file
1235						 * descriptor:
1236						 */
1237						nfds = i;
1238					}
1239				}
1240				/*
1241				 * Check if this file descriptor is set for
1242				 * write:
1243				 */
1244				if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
1245					/*
1246					 * Add the file descriptor to the
1247					 * write set:
1248					 */
1249					FD_SET(i, &fd_set_write);
1250
1251					/*
1252					 * Increment the file descriptor
1253					 * count:
1254					 */
1255					count++;
1256
1257					/*
1258					 * Check if this file descriptor is
1259					 * greater than any of those seen so
1260					 * far:
1261					 */
1262					if (i > nfds) {
1263						/*
1264						 * Remember this file
1265						 * descriptor:
1266						 */
1267						nfds = i;
1268					}
1269				}
1270				/*
1271				 * Check if this file descriptor is set for
1272				 * read:
1273				 */
1274				if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
1275					/*
1276					 * Add the file descriptor to the
1277					 * read set:
1278					 */
1279					FD_SET(i, &fd_set_read);
1280
1281					/*
1282					 * Increment the file descriptor
1283					 * count:
1284					 */
1285					count++;
1286
1287					/*
1288					 * Check if this file descriptor is
1289					 * greater than any of those seen so
1290					 * far:
1291					 */
1292					if (i > nfds) {
1293						/*
1294						 * Remember this file
1295						 * descriptor:
1296						 */
1297						nfds = i;
1298					}
1299				}
1300			}
1301
1302			/* This state can time out: */
1303			settimeout = 1;
1304			break;
1305		}
1306
1307		/*
1308		 * Check if the caller wants to wait and if the thread state
1309		 * is one that times out:
1310		 */
1311		if (wait_reqd && settimeout) {
1312			/* Check if this thread wants to wait forever: */
1313			if (pthread->wakeup_time.tv_sec == -1) {
1314			}
1315			/* Check if this thread doesn't want to wait at all: */
1316			else if (pthread->wakeup_time.tv_sec == 0 &&
1317				 pthread->wakeup_time.tv_nsec == 0) {
1318				/* Override the caller's request to wait: */
1319				wait_reqd = 0;
1320			} else {
1321				/*
1322				 * Calculate the time until this thread is
1323				 * ready, allowing for the clock resolution:
1324				 */
1325				ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
1326				ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
1327					CLOCK_RES_NSEC;
1328
1329				/*
1330				 * Check for underflow of the nanosecond
1331				 * field:
1332				 */
1333				if (ts1.tv_nsec < 0) {
1334					/*
1335					 * Allow for the underflow of the
1336					 * nanosecond field:
1337					 */
1338					ts1.tv_sec--;
1339					ts1.tv_nsec += 1000000000;
1340				}
1341				/*
1342				 * Check for overflow of the nanosecond
1343				 * field:
1344				 */
1345				if (ts1.tv_nsec >= 1000000000) {
1346					/*
1347					 * Allow for the overflow of the
1348					 * nanosecond field:
1349					 */
1350					ts1.tv_sec++;
1351					ts1.tv_nsec -= 1000000000;
1352				}
1353				/*
1354				 * Convert the timespec structure to a
1355				 * timeval structure:
1356				 */
1357				TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
1358
1359				/*
1360				 * Check if no time value has been found yet,
1361				 * or if the thread will be ready sooner that
1362				 * the earliest one found so far:
1363				 */
1364				if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
1365					/* Update the time value: */
1366					tv.tv_sec = tv1.tv_sec;
1367					tv.tv_usec = tv1.tv_usec;
1368				}
1369			}
1370		}
1371	}
1372
1373	/* Check if the caller wants to wait: */
1374	if (wait_reqd) {
1375		/* Check if no threads were found with timeouts: */
1376		if (tv.tv_sec == 0 && tv.tv_usec == 0) {
1377			/* Wait forever: */
1378			p_tv = NULL;
1379		} else {
1380			/*
1381			 * Point to the time value structure which contains
1382			 * the earliest time that a thread will be ready:
1383			 */
1384			p_tv = &tv;
1385		}
1386
1387		/*
1388		 * Flag the pthread kernel as in a select. This is to avoid
1389		 * the window between the next statement that unblocks
1390		 * signals and the select statement which follows.
1391		 */
1392		_thread_kern_in_select = 1;
1393
1394		/* Unblock all signals: */
1395		_thread_kern_sig_unblock(0);
1396
1397		/*
1398		 * Wait for a file descriptor to be ready for read, write, or
1399		 * an exception, or a timeout to occur:
1400		 */
1401		count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
1402
1403		/* Block all signals again: */
1404		_thread_kern_sig_block(NULL);
1405
1406		/* Reset the kernel in select flag: */
1407		_thread_kern_in_select = 0;
1408
1409		/*
1410		 * Check if it is possible that there are bytes in the kernel
1411		 * read pipe waiting to be read:
1412		 */
1413		if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
1414			/*
1415			 * Check if the kernel read pipe was included in the
1416			 * count:
1417			 */
1418			if (count > 0) {
1419				/*
1420				 * Remove the kernel read pipe from the
1421				 * count:
1422				 */
1423				FD_CLR(_thread_kern_pipe[0], &fd_set_read);
1424
1425				/* Decrement the count of file descriptors: */
1426				count--;
1427			}
1428			/*
1429			 * Enter a loop to read (and trash) bytes from the
1430			 * pthread kernel pipe:
1431			 */
1432			while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
1433				/*
1434				 * The buffer read contains one byte per
1435				 * signal and each byte is the signal number.
1436				 * This data is not used, but the fact that
1437				 * the signal handler wrote to the pipe *is*
1438				 * used to cause the _thread_sys_select call
1439				 * to complete if the signal occurred between
1440				 * the time when signals were unblocked and
1441				 * the _thread_sys_select select call being
1442				 * made.
1443				 */
1444			}
1445		}
1446	}
1447	/* Check if there are file descriptors to poll: */
1448	else if (count > 0) {
1449		/*
1450		 * Point to the time value structure which has been zeroed so
1451		 * that the call to _thread_sys_select will not wait:
1452		 */
1453		p_tv = &tv;
1454
1455		/* Poll file descrptors without wait: */
1456		count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
1457	}
1458	/*
1459	 * Check if the select call was interrupted, or some other error
1460	 * occurred:
1461	 */
1462	if (count < 0) {
1463		/* Check if the select call was interrupted: */
1464		if (errno == EINTR) {
1465			/*
1466			 * Interrupted calls are expected. The interrupting
1467			 * signal will be in the sigpend array.
1468			 */
1469		} else {
1470			/* This should not occur: */
1471		}
1472	}
1473	/* Check if no file descriptors are ready: */
1474	else if (count == 0) {
1475		/* Nothing to do here.                                              */
1476	} else {
1477		/*
1478		 * Enter a loop to look for threads waiting on file
1479		 * descriptors that are flagged as available by the
1480		 * _thread_sys_select syscall:
1481		 */
1482		for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
1483			/* Process according to thread state: */
1484			switch (pthread->state) {
1485			/*
1486			 * States which do not depend on file
1487			 * descriptor I/O operations:
1488			 */
1489			case PS_RUNNING:
1490			case PS_COND_WAIT:
1491			case PS_DEAD:
1492			case PS_FDLR_WAIT:
1493			case PS_FDLW_WAIT:
1494			case PS_JOIN:
1495			case PS_MUTEX_WAIT:
1496			case PS_SIGWAIT:
1497			case PS_SLEEP_WAIT:
1498			case PS_WAIT_WAIT:
1499			case PS_SIGTHREAD:
1500			case PS_STATE_MAX:
1501			case PS_SUSPENDED:
1502				/* Nothing to do here. */
1503				break;
1504
1505			/* File descriptor read wait: */
1506			case PS_FDR_WAIT:
1507				/*
1508				 * Check if the file descriptor is available
1509				 * for read:
1510				 */
1511				if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
1512					/*
1513					 * Change the thread state to allow
1514					 * it to read from the file when it
1515					 * is scheduled next:
1516					 */
1517					pthread->state = PS_RUNNING;
1518				}
1519				break;
1520
1521			/* File descriptor write wait: */
1522			case PS_FDW_WAIT:
1523				/*
1524				 * Check if the file descriptor is available
1525				 * for write:
1526				 */
1527				if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
1528					/*
1529					 * Change the thread state to allow
1530					 * it to write to the file when it is
1531					 * scheduled next:
1532					 */
1533					pthread->state = PS_RUNNING;
1534				}
1535				break;
1536
1537			/* Select wait: */
1538			case PS_SELECT_WAIT:
1539				/*
1540				 * Reset the flag that indicates if a file
1541				 * descriptor is ready for some type of
1542				 * operation:
1543				 */
1544				count_dec = 0;
1545
1546				/*
1547				 * Enter a loop to search though the
1548				 * thread-specific select file descriptors
1549				 * for the first descriptor that is ready:
1550				 */
1551				for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
1552					/*
1553					 * Check if this file descriptor does
1554					 * not have an exception:
1555					 */
1556					if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
1557						/*
1558						 * Flag this file descriptor
1559						 * as ready:
1560						 */
1561						count_dec = 1;
1562					}
1563					/*
1564					 * Check if this file descriptor is
1565					 * not ready for write:
1566					 */
1567					if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
1568						/*
1569						 * Flag this file descriptor
1570						 * as ready:
1571						 */
1572						count_dec = 1;
1573					}
1574					/*
1575					 * Check if this file descriptor is
1576					 * not ready for read:
1577					 */
1578					if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
1579						/*
1580						 * Flag this file descriptor
1581						 * as ready:
1582						 */
1583						count_dec = 1;
1584					}
1585				}
1586
1587				/*
1588				 * Check if any file descriptors are ready
1589				 * for the current thread:
1590				 */
1591				if (count_dec) {
1592					/*
1593					 * Reset the count of file
1594					 * descriptors that are ready for
1595					 * this thread:
1596					 */
1597					found_one = 0;
1598
1599					/*
1600					 * Enter a loop to search though the
1601					 * thread-specific select file
1602					 * descriptors:
1603					 */
1604					for (i = 0; i < pthread->data.select_data->nfds; i++) {
1605						/*
1606						 * Reset the count of
1607						 * operations for which the
1608						 * current file descriptor is
1609						 * ready:
1610						 */
1611						count_dec = 0;
1612
1613						/*
1614						 * Check if this file
1615						 * descriptor is selected for
1616						 * exceptions:
1617						 */
1618						if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
1619							/*
1620							 * Check if this file
1621							 * descriptor has an
1622							 * exception:
1623							 */
1624							if (FD_ISSET(i, &fd_set_except)) {
1625								/*
1626								 * Increment
1627								 * the count
1628								 * for this
1629								 * file:
1630								 */
1631								count_dec++;
1632							} else {
1633								/*
1634								 * Clear the
1635								 * file
1636								 * descriptor
1637								 * in the
1638								 * thread-spec
1639								 * ific file
1640								 * descriptor
1641								 * set:
1642								 */
1643								FD_CLR(i, &pthread->data.select_data->exceptfds);
1644							}
1645						}
1646						/*
1647						 * Check if this file
1648						 * descriptor is selected for
1649						 * write:
1650						 */
1651						if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
1652							/*
1653							 * Check if this file
1654							 * descriptor is
1655							 * ready for write:
1656							 */
1657							if (FD_ISSET(i, &fd_set_write)) {
1658								/*
1659								 * Increment
1660								 * the count
1661								 * for this
1662								 * file:
1663								 */
1664								count_dec++;
1665							} else {
1666								/*
1667								 * Clear the
1668								 * file
1669								 * descriptor
1670								 * in the
1671								 * thread-spec
1672								 * ific file
1673								 * descriptor
1674								 * set:
1675								 */
1676								FD_CLR(i, &pthread->data.select_data->writefds);
1677							}
1678						}
1679						/*
1680						 * Check if this file
1681						 * descriptor is selected for
1682						 * read:
1683						 */
1684						if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
1685							/*
1686							 * Check if this file
1687							 * descriptor is
1688							 * ready for read:
1689							 */
1690							if (FD_ISSET(i, &fd_set_read)) {
1691								/*
1692								 * Increment
1693								 * the count
1694								 * for this
1695								 * file:
1696								 */
1697								count_dec++;
1698							} else {
1699								/*
1700								 * Clear the
1701								 * file
1702								 * descriptor
1703								 * in the
1704								 * thread-spec
1705								 * ific file
1706								 * descriptor
1707								 * set:
1708								 */
1709								FD_CLR(i, &pthread->data.select_data->readfds);
1710							}
1711						}
1712						/*
1713						 * Check if the current file
1714						 * descriptor is ready for
1715						 * any one of the operations:
1716						 */
1717						if (count_dec > 0) {
1718							/*
1719							 * Increment the
1720							 * count of file
1721							 * descriptors that
1722							 * are ready for the
1723							 * current thread:
1724							 */
1725							found_one++;
1726						}
1727					}
1728
1729					/*
1730					 * Return the number of file
1731					 * descriptors that are ready:
1732					 */
1733					pthread->data.select_data->nfds = found_one;
1734
1735					/*
1736					 * Change the state of the current
1737					 * thread to run:
1738					 */
1739					pthread->state = PS_RUNNING;
1740				}
1741				break;
1742			}
1743		}
1744	}
1745
1746	/* Nothing to return. */
1747	return;
1748}
1749
1750void
1751_thread_kern_set_timeout(struct timespec * timeout)
1752{
1753	struct timespec current_time;
1754	struct timeval  tv;
1755
1756	/* Reset the timeout flag for the running thread: */
1757	_thread_run->timeout = 0;
1758
1759	/* Check if the thread is to wait forever: */
1760	if (timeout == NULL) {
1761		/*
1762		 * Set the wakeup time to something that can be recognised as
1763		 * different to an actual time of day:
1764		 */
1765		_thread_run->wakeup_time.tv_sec = -1;
1766		_thread_run->wakeup_time.tv_nsec = -1;
1767	}
1768	/* Check if no waiting is required: */
1769	else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
1770		/* Set the wake up time to 'immediately': */
1771		_thread_run->wakeup_time.tv_sec = 0;
1772		_thread_run->wakeup_time.tv_nsec = 0;
1773	} else {
1774		/* Get the current time: */
1775		gettimeofday(&tv, NULL);
1776		TIMEVAL_TO_TIMESPEC(&tv, &current_time);
1777
1778		/* Calculate the time for the current thread to wake up: */
1779		_thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
1780		_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
1781
1782		/* Check if the nanosecond field needs to wrap: */
1783		if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
1784			/* Wrap the nanosecond field: */
1785			_thread_run->wakeup_time.tv_sec += 1;
1786			_thread_run->wakeup_time.tv_nsec -= 1000000000;
1787		}
1788	}
1789	return;
1790}
1791#endif
1792