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