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, ¤t_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