thr_kern.c revision 24520
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$
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		/* Default processing for other signals: */
953		default:
954			/*
955			 * ### Default processing is a problem to resolve!
956			 * ###
957			 */
958			break;
959		}
960	} else {
961		/*
962		 * Cast the signal number as a long and then to a void
963		 * pointer. Sigh. This is POSIX.
964		 */
965		l = (long) sig;
966		arg = (void *) l;
967
968		/* Create a signal handler thread, but don't run it yet: */
969		if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
970			/*
971			 * Error creating signal handler thread, so abort
972			 * this process:
973			 */
974			PANIC("Cannot create signal handler thread");
975		}
976	}
977
978	/* Nothing to return. */
979	return;
980}
981
982void
983_thread_kern_sig_block(int *status)
984{
985	sigset_t        oset;
986
987	/*
988	 * Block all signals so that the process will not be interrupted by
989	 * signals:
990	 */
991	_thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
992
993	/* Check if the caller wants the current block status returned: */
994	if (status != NULL) {
995		/* Return the previous signal block status: */
996		*status = (oset != 0);
997	}
998	return;
999}
1000
1001void
1002_thread_kern_sig_unblock(int status)
1003{
1004	sigset_t        oset;
1005
1006	/*
1007	 * Check if the caller thinks that signals weren't blocked when it
1008	 * called _thread_kern_sig_block:
1009	 */
1010	if (status == 0) {
1011		/*
1012		 * Unblock all signals so that the process will be
1013		 * interrupted when a signal occurs:
1014		 */
1015		_thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
1016	}
1017	return;
1018}
1019
1020void
1021_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
1022{
1023	/* Change the state of the current thread: */
1024	_thread_run->state = state;
1025	_thread_run->fname = fname;
1026	_thread_run->lineno = lineno;
1027
1028	/* Schedule the next thread that is ready: */
1029	_thread_kern_sched(NULL);
1030	return;
1031}
1032
1033static void
1034_thread_kern_select(int wait_reqd)
1035{
1036	char            bufr[128];
1037	fd_set          fd_set_except;
1038	fd_set          fd_set_read;
1039	fd_set          fd_set_write;
1040	int             count = 0;
1041	int             count_dec;
1042	int             found_one;
1043	int             i;
1044	int             nfds = -1;
1045	int             settimeout;
1046	pthread_t       pthread;
1047	ssize_t         num;
1048	struct timespec ts;
1049	struct timespec ts1;
1050	struct timeval *p_tv;
1051	struct timeval  tv;
1052	struct timeval  tv1;
1053
1054	/* Zero the file descriptor sets: */
1055	FD_ZERO(&fd_set_read);
1056	FD_ZERO(&fd_set_write);
1057	FD_ZERO(&fd_set_except);
1058
1059	/* Check if the caller wants to wait: */
1060	if (wait_reqd) {
1061		/*
1062		 * Add the pthread kernel pipe file descriptor to the read
1063		 * set:
1064		 */
1065		FD_SET(_thread_kern_pipe[0], &fd_set_read);
1066		nfds = _thread_kern_pipe[0];
1067
1068		/* Get the current time of day: */
1069		gettimeofday(&tv, NULL);
1070		TIMEVAL_TO_TIMESPEC(&tv, &ts);
1071	}
1072	/* Initialise the time value structure: */
1073	tv.tv_sec = 0;
1074	tv.tv_usec = 0;
1075
1076	/*
1077	 * Enter a loop to process threads waiting on either file descriptors
1078	 * or times:
1079	 */
1080	for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
1081		/* Assume that this state does not time out: */
1082		settimeout = 0;
1083
1084		/* Process according to thread state: */
1085		switch (pthread->state) {
1086		/*
1087		 * States which do not depend on file descriptor I/O
1088		 * operations or timeouts:
1089		 */
1090		case PS_DEAD:
1091		case PS_FDLR_WAIT:
1092		case PS_FDLW_WAIT:
1093		case PS_JOIN:
1094		case PS_MUTEX_WAIT:
1095		case PS_RUNNING:
1096		case PS_SIGTHREAD:
1097		case PS_SIGWAIT:
1098		case PS_STATE_MAX:
1099		case PS_WAIT_WAIT:
1100		case PS_SUSPENDED:
1101			/* Nothing to do here. */
1102			break;
1103
1104		/* File descriptor read wait: */
1105		case PS_FDR_WAIT:
1106			/* Add the file descriptor to the read set: */
1107			FD_SET(pthread->data.fd.fd, &fd_set_read);
1108
1109			/*
1110			 * Check if this file descriptor is greater than any
1111			 * of those seen so far:
1112			 */
1113			if (pthread->data.fd.fd > nfds) {
1114				/* Remember this file descriptor: */
1115				nfds = pthread->data.fd.fd;
1116			}
1117			/* Increment the file descriptor count: */
1118			count++;
1119
1120			/* This state can time out: */
1121			settimeout = 1;
1122			break;
1123
1124		/* File descriptor write wait: */
1125		case PS_FDW_WAIT:
1126			/* Add the file descriptor to the write set: */
1127			FD_SET(pthread->data.fd.fd, &fd_set_write);
1128
1129			/*
1130			 * Check if this file descriptor is greater than any
1131			 * of those seen so far:
1132			 */
1133			if (pthread->data.fd.fd > nfds) {
1134				/* Remember this file descriptor: */
1135				nfds = pthread->data.fd.fd;
1136			}
1137			/* Increment the file descriptor count: */
1138			count++;
1139
1140			/* This state can time out: */
1141			settimeout = 1;
1142			break;
1143
1144		/* States that time out: */
1145		case PS_SLEEP_WAIT:
1146		case PS_COND_WAIT:
1147			/* Flag a timeout as required: */
1148			settimeout = 1;
1149			break;
1150
1151		/* Select wait: */
1152		case PS_SELECT_WAIT:
1153			/*
1154			 * Enter a loop to process each file descriptor in
1155			 * the thread-specific file descriptor sets:
1156			 */
1157			for (i = 0; i < pthread->data.select_data->nfds; i++) {
1158				/*
1159				 * Check if this file descriptor is set for
1160				 * exceptions:
1161				 */
1162				if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
1163					/*
1164					 * Add the file descriptor to the
1165					 * exception set:
1166					 */
1167					FD_SET(i, &fd_set_except);
1168
1169					/*
1170					 * Increment the file descriptor
1171					 * count:
1172					 */
1173					count++;
1174
1175					/*
1176					 * Check if this file descriptor is
1177					 * greater than any of those seen so
1178					 * far:
1179					 */
1180					if (i > nfds) {
1181						/*
1182						 * Remember this file
1183						 * descriptor:
1184						 */
1185						nfds = i;
1186					}
1187				}
1188				/*
1189				 * Check if this file descriptor is set for
1190				 * write:
1191				 */
1192				if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
1193					/*
1194					 * Add the file descriptor to the
1195					 * write set:
1196					 */
1197					FD_SET(i, &fd_set_write);
1198
1199					/*
1200					 * Increment the file descriptor
1201					 * count:
1202					 */
1203					count++;
1204
1205					/*
1206					 * Check if this file descriptor is
1207					 * greater than any of those seen so
1208					 * far:
1209					 */
1210					if (i > nfds) {
1211						/*
1212						 * Remember this file
1213						 * descriptor:
1214						 */
1215						nfds = i;
1216					}
1217				}
1218				/*
1219				 * Check if this file descriptor is set for
1220				 * read:
1221				 */
1222				if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
1223					/*
1224					 * Add the file descriptor to the
1225					 * read set:
1226					 */
1227					FD_SET(i, &fd_set_read);
1228
1229					/*
1230					 * Increment the file descriptor
1231					 * count:
1232					 */
1233					count++;
1234
1235					/*
1236					 * Check if this file descriptor is
1237					 * greater than any of those seen so
1238					 * far:
1239					 */
1240					if (i > nfds) {
1241						/*
1242						 * Remember this file
1243						 * descriptor:
1244						 */
1245						nfds = i;
1246					}
1247				}
1248			}
1249
1250			/* This state can time out: */
1251			settimeout = 1;
1252			break;
1253		}
1254
1255		/*
1256		 * Check if the caller wants to wait and if the thread state
1257		 * is one that times out:
1258		 */
1259		if (wait_reqd && settimeout) {
1260			/* Check if this thread wants to wait forever: */
1261			if (pthread->wakeup_time.tv_sec == -1) {
1262			}
1263			/* Check if this thread doesn't want to wait at all: */
1264			else if (pthread->wakeup_time.tv_sec == 0 &&
1265				 pthread->wakeup_time.tv_nsec == 0) {
1266				/* Override the caller's request to wait: */
1267				wait_reqd = 0;
1268			} else {
1269				/*
1270				 * Calculate the time until this thread is
1271				 * ready, allowing for the clock resolution:
1272				 */
1273				ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
1274				ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
1275					CLOCK_RES_NSEC;
1276
1277				/*
1278				 * Check for underflow of the nanosecond
1279				 * field:
1280				 */
1281				if (ts1.tv_nsec < 0) {
1282					/*
1283					 * Allow for the underflow of the
1284					 * nanosecond field:
1285					 */
1286					ts1.tv_sec--;
1287					ts1.tv_nsec += 1000000000;
1288				}
1289				/*
1290				 * Check for overflow of the nanosecond
1291				 * field:
1292				 */
1293				if (ts1.tv_nsec >= 1000000000) {
1294					/*
1295					 * Allow for the overflow of the
1296					 * nanosecond field:
1297					 */
1298					ts1.tv_sec++;
1299					ts1.tv_nsec -= 1000000000;
1300				}
1301				/*
1302				 * Convert the timespec structure to a
1303				 * timeval structure:
1304				 */
1305				TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
1306
1307				/*
1308				 * Check if no time value has been found yet,
1309				 * or if the thread will be ready sooner that
1310				 * the earliest one found so far:
1311				 */
1312				if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
1313					/* Update the time value: */
1314					tv.tv_sec = tv1.tv_sec;
1315					tv.tv_usec = tv1.tv_usec;
1316				}
1317			}
1318		}
1319	}
1320
1321	/* Check if the caller wants to wait: */
1322	if (wait_reqd) {
1323		/* Check if no threads were found with timeouts: */
1324		if (tv.tv_sec == 0 && tv.tv_usec == 0) {
1325			/* Wait forever: */
1326			p_tv = NULL;
1327		} else {
1328			/*
1329			 * Point to the time value structure which contains
1330			 * the earliest time that a thread will be ready:
1331			 */
1332			p_tv = &tv;
1333		}
1334
1335		/*
1336		 * Flag the pthread kernel as in a select. This is to avoid
1337		 * the window between the next statement that unblocks
1338		 * signals and the select statement which follows.
1339		 */
1340		_thread_kern_in_select = 1;
1341
1342		/* Unblock all signals: */
1343		_thread_kern_sig_unblock(0);
1344
1345		/*
1346		 * Wait for a file descriptor to be ready for read, write, or
1347		 * an exception, or a timeout to occur:
1348		 */
1349		count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
1350
1351		/* Block all signals again: */
1352		_thread_kern_sig_block(NULL);
1353
1354		/* Reset the kernel in select flag: */
1355		_thread_kern_in_select = 0;
1356
1357		/*
1358		 * Check if it is possible that there are bytes in the kernel
1359		 * read pipe waiting to be read:
1360		 */
1361		if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
1362			/*
1363			 * Check if the kernel read pipe was included in the
1364			 * count:
1365			 */
1366			if (count > 0) {
1367				/*
1368				 * Remove the kernel read pipe from the
1369				 * count:
1370				 */
1371				FD_CLR(_thread_kern_pipe[0], &fd_set_read);
1372
1373				/* Decrement the count of file descriptors: */
1374				count--;
1375			}
1376			/*
1377			 * Enter a loop to read (and trash) bytes from the
1378			 * pthread kernel pipe:
1379			 */
1380			while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
1381				/*
1382				 * The buffer read contains one byte per
1383				 * signal and each byte is the signal number.
1384				 * This data is not used, but the fact that
1385				 * the signal handler wrote to the pipe *is*
1386				 * used to cause the _thread_sys_select call
1387				 * to complete if the signal occurred between
1388				 * the time when signals were unblocked and
1389				 * the _thread_sys_select select call being
1390				 * made.
1391				 */
1392			}
1393		}
1394	}
1395	/* Check if there are file descriptors to poll: */
1396	else if (count > 0) {
1397		/*
1398		 * Point to the time value structure which has been zeroed so
1399		 * that the call to _thread_sys_select will not wait:
1400		 */
1401		p_tv = &tv;
1402
1403		/* Poll file descrptors without wait: */
1404		count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
1405	}
1406	/*
1407	 * Check if the select call was interrupted, or some other error
1408	 * occurred:
1409	 */
1410	if (count < 0) {
1411		/* Check if the select call was interrupted: */
1412		if (errno == EINTR) {
1413			/*
1414			 * Interrupted calls are expected. The interrupting
1415			 * signal will be in the sigpend array.
1416			 */
1417		} else {
1418			/* This should not occur: */
1419		}
1420	}
1421	/* Check if no file descriptors are ready: */
1422	else if (count == 0) {
1423		/* Nothing to do here.                                              */
1424	} else {
1425		/*
1426		 * Enter a loop to look for threads waiting on file
1427		 * descriptors that are flagged as available by the
1428		 * _thread_sys_select syscall:
1429		 */
1430		for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
1431			/* Process according to thread state: */
1432			switch (pthread->state) {
1433			/*
1434			 * States which do not depend on file
1435			 * descriptor I/O operations:
1436			 */
1437			case PS_RUNNING:
1438			case PS_COND_WAIT:
1439			case PS_DEAD:
1440			case PS_FDLR_WAIT:
1441			case PS_FDLW_WAIT:
1442			case PS_JOIN:
1443			case PS_MUTEX_WAIT:
1444			case PS_SIGWAIT:
1445			case PS_SLEEP_WAIT:
1446			case PS_WAIT_WAIT:
1447			case PS_SIGTHREAD:
1448			case PS_STATE_MAX:
1449			case PS_SUSPENDED:
1450				/* Nothing to do here. */
1451				break;
1452
1453			/* File descriptor read wait: */
1454			case PS_FDR_WAIT:
1455				/*
1456				 * Check if the file descriptor is available
1457				 * for read:
1458				 */
1459				if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
1460					/*
1461					 * Change the thread state to allow
1462					 * it to read from the file when it
1463					 * is scheduled next:
1464					 */
1465					pthread->state = PS_RUNNING;
1466				}
1467				break;
1468
1469			/* File descriptor write wait: */
1470			case PS_FDW_WAIT:
1471				/*
1472				 * Check if the file descriptor is available
1473				 * for write:
1474				 */
1475				if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
1476					/*
1477					 * Change the thread state to allow
1478					 * it to write to the file when it is
1479					 * scheduled next:
1480					 */
1481					pthread->state = PS_RUNNING;
1482				}
1483				break;
1484
1485			/* Select wait: */
1486			case PS_SELECT_WAIT:
1487				/*
1488				 * Reset the flag that indicates if a file
1489				 * descriptor is ready for some type of
1490				 * operation:
1491				 */
1492				count_dec = 0;
1493
1494				/*
1495				 * Enter a loop to search though the
1496				 * thread-specific select file descriptors
1497				 * for the first descriptor that is ready:
1498				 */
1499				for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
1500					/*
1501					 * Check if this file descriptor does
1502					 * not have an exception:
1503					 */
1504					if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
1505						/*
1506						 * Flag this file descriptor
1507						 * as ready:
1508						 */
1509						count_dec = 1;
1510					}
1511					/*
1512					 * Check if this file descriptor is
1513					 * not ready for write:
1514					 */
1515					if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
1516						/*
1517						 * Flag this file descriptor
1518						 * as ready:
1519						 */
1520						count_dec = 1;
1521					}
1522					/*
1523					 * Check if this file descriptor is
1524					 * not ready for read:
1525					 */
1526					if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
1527						/*
1528						 * Flag this file descriptor
1529						 * as ready:
1530						 */
1531						count_dec = 1;
1532					}
1533				}
1534
1535				/*
1536				 * Check if any file descriptors are ready
1537				 * for the current thread:
1538				 */
1539				if (count_dec) {
1540					/*
1541					 * Reset the count of file
1542					 * descriptors that are ready for
1543					 * this thread:
1544					 */
1545					found_one = 0;
1546
1547					/*
1548					 * Enter a loop to search though the
1549					 * thread-specific select file
1550					 * descriptors:
1551					 */
1552					for (i = 0; i < pthread->data.select_data->nfds; i++) {
1553						/*
1554						 * Reset the count of
1555						 * operations for which the
1556						 * current file descriptor is
1557						 * ready:
1558						 */
1559						count_dec = 0;
1560
1561						/*
1562						 * Check if this file
1563						 * descriptor is selected for
1564						 * exceptions:
1565						 */
1566						if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
1567							/*
1568							 * Check if this file
1569							 * descriptor has an
1570							 * exception:
1571							 */
1572							if (FD_ISSET(i, &fd_set_except)) {
1573								/*
1574								 * Increment
1575								 * the count
1576								 * for this
1577								 * file:
1578								 */
1579								count_dec++;
1580							} else {
1581								/*
1582								 * Clear the
1583								 * file
1584								 * descriptor
1585								 * in the
1586								 * thread-spec
1587								 * ific file
1588								 * descriptor
1589								 * set:
1590								 */
1591								FD_CLR(i, &pthread->data.select_data->exceptfds);
1592							}
1593						}
1594						/*
1595						 * Check if this file
1596						 * descriptor is selected for
1597						 * write:
1598						 */
1599						if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
1600							/*
1601							 * Check if this file
1602							 * descriptor is
1603							 * ready for write:
1604							 */
1605							if (FD_ISSET(i, &fd_set_write)) {
1606								/*
1607								 * Increment
1608								 * the count
1609								 * for this
1610								 * file:
1611								 */
1612								count_dec++;
1613							} else {
1614								/*
1615								 * Clear the
1616								 * file
1617								 * descriptor
1618								 * in the
1619								 * thread-spec
1620								 * ific file
1621								 * descriptor
1622								 * set:
1623								 */
1624								FD_CLR(i, &pthread->data.select_data->writefds);
1625							}
1626						}
1627						/*
1628						 * Check if this file
1629						 * descriptor is selected for
1630						 * read:
1631						 */
1632						if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
1633							/*
1634							 * Check if this file
1635							 * descriptor is
1636							 * ready for read:
1637							 */
1638							if (FD_ISSET(i, &fd_set_read)) {
1639								/*
1640								 * Increment
1641								 * the count
1642								 * for this
1643								 * file:
1644								 */
1645								count_dec++;
1646							} else {
1647								/*
1648								 * Clear the
1649								 * file
1650								 * descriptor
1651								 * in the
1652								 * thread-spec
1653								 * ific file
1654								 * descriptor
1655								 * set:
1656								 */
1657								FD_CLR(i, &pthread->data.select_data->readfds);
1658							}
1659						}
1660						/*
1661						 * Check if the current file
1662						 * descriptor is ready for
1663						 * any one of the operations:
1664						 */
1665						if (count_dec > 0) {
1666							/*
1667							 * Increment the
1668							 * count of file
1669							 * descriptors that
1670							 * are ready for the
1671							 * current thread:
1672							 */
1673							found_one++;
1674						}
1675					}
1676
1677					/*
1678					 * Return the number of file
1679					 * descriptors that are ready:
1680					 */
1681					pthread->data.select_data->nfds = found_one;
1682
1683					/*
1684					 * Change the state of the current
1685					 * thread to run:
1686					 */
1687					pthread->state = PS_RUNNING;
1688				}
1689				break;
1690			}
1691		}
1692	}
1693
1694	/* Nothing to return. */
1695	return;
1696}
1697
1698void
1699_thread_kern_set_timeout(struct timespec * timeout)
1700{
1701	struct timespec current_time;
1702	struct timeval  tv;
1703
1704	/* Reset the timeout flag for the running thread: */
1705	_thread_run->timeout = 0;
1706
1707	/* Check if the thread is to wait forever: */
1708	if (timeout == NULL) {
1709		/*
1710		 * Set the wakeup time to something that can be recognised as
1711		 * different to an actual time of day:
1712		 */
1713		_thread_run->wakeup_time.tv_sec = -1;
1714		_thread_run->wakeup_time.tv_nsec = -1;
1715	}
1716	/* Check if no waiting is required: */
1717	else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
1718		/* Set the wake up time to 'immediately': */
1719		_thread_run->wakeup_time.tv_sec = 0;
1720		_thread_run->wakeup_time.tv_nsec = 0;
1721	} else {
1722		/* Get the current time: */
1723		gettimeofday(&tv, NULL);
1724		TIMEVAL_TO_TIMESPEC(&tv, &current_time);
1725
1726		/* Calculate the time for the current thread to wake up: */
1727		_thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
1728		_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
1729
1730		/* Check if the nanosecond field needs to wrap: */
1731		if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
1732			/* Wrap the nanosecond field: */
1733			_thread_run->wakeup_time.tv_sec += 1;
1734			_thread_run->wakeup_time.tv_nsec -= 1000000000;
1735		}
1736	}
1737	return;
1738}
1739#endif
1740