unix.c (93613B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "primpl.h" 7 8 #include <string.h> 9 #include <signal.h> 10 #include <unistd.h> 11 #include <fcntl.h> 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <sys/time.h> 15 #include <sys/ioctl.h> 16 #include <sys/mman.h> 17 #include <unistd.h> 18 #include <sys/utsname.h> 19 20 #ifdef _PR_POLL_AVAILABLE 21 # include <poll.h> 22 #endif 23 24 #if defined(ANDROID) 25 # include <android/api-level.h> 26 #endif 27 28 #if defined(NTO) 29 # include <sys/statvfs.h> 30 #endif 31 32 /* 33 * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or 34 * PRInt32* pointer to a _PRSockLen_t* pointer. 35 */ 36 #if defined(HAVE_SOCKLEN_T) || (defined(__GLIBC__) && __GLIBC__ >= 2) 37 # define _PRSockLen_t socklen_t 38 #elif defined(SOLARIS) || defined(AIX4_1) || \ 39 defined(LINUX) || defined(DARWIN) || defined(QNX) 40 # define _PRSockLen_t int 41 #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) || \ 42 defined(NETBSD) || defined(OPENBSD) 43 || defined(NTO) || 44 defined(RISCOS) 45 # define _PRSockLen_t size_t 46 #else 47 # error "Cannot determine architecture" 48 #endif 49 50 /* 51 ** Global lock variable used to bracket calls into rusty libraries that 52 ** aren't thread safe (like libc, libX, etc). 53 */ 54 static PRLock* _pr_unix_rename_lock = NULL; 55 static PRMonitor* _pr_Xfe_mon = NULL; 56 57 static PRInt64 minus_one; 58 59 sigset_t timer_set; 60 61 #if !defined(_PR_PTHREADS) 62 63 static sigset_t empty_set; 64 65 # ifdef SOLARIS 66 # include <sys/file.h> 67 # include <sys/filio.h> 68 # endif 69 70 # ifndef PIPE_BUF 71 # define PIPE_BUF 512 72 # endif 73 74 /* 75 * _nspr_noclock - if set clock interrupts are disabled 76 */ 77 int _nspr_noclock = 1; 78 79 /* 80 * There is an assertion in this code that NSPR's definition of PRIOVec 81 * is bit compatible with UNIX' definition of a struct iovec. This is 82 * applicable to the 'writev()' operations where the types are casually 83 * cast to avoid warnings. 84 */ 85 86 int _pr_md_pipefd[2] = {-1, -1}; 87 static char _pr_md_pipebuf[PIPE_BUF]; 88 static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag, 89 PRIntervalTime timeout); 90 91 _PRInterruptTable _pr_interruptTable[] = {{ 92 "clock", 93 _PR_MISSED_CLOCK, 94 _PR_ClockInterrupt, 95 }, 96 {0}}; 97 98 void _MD_unix_init_running_cpu(_PRCPU* cpu) { 99 PR_INIT_CLIST(&(cpu->md.md_unix.ioQ)); 100 cpu->md.md_unix.ioq_max_osfd = -1; 101 cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT; 102 } 103 104 PRStatus _MD_open_dir(_MDDir* d, const char* name) { 105 int err; 106 107 d->d = opendir(name); 108 if (!d->d) { 109 err = _MD_ERRNO(); 110 _PR_MD_MAP_OPENDIR_ERROR(err); 111 return PR_FAILURE; 112 } 113 return PR_SUCCESS; 114 } 115 116 PRInt32 _MD_close_dir(_MDDir* d) { 117 int rv = 0, err; 118 119 if (d->d) { 120 rv = closedir(d->d); 121 if (rv == -1) { 122 err = _MD_ERRNO(); 123 _PR_MD_MAP_CLOSEDIR_ERROR(err); 124 } 125 } 126 return rv; 127 } 128 129 char* _MD_read_dir(_MDDir* d, PRIntn flags) { 130 struct dirent* de; 131 int err; 132 133 for (;;) { 134 /* 135 * XXX: readdir() is not MT-safe. There is an MT-safe version 136 * readdir_r() on some systems. 137 */ 138 _MD_ERRNO() = 0; 139 de = readdir(d->d); 140 if (!de) { 141 err = _MD_ERRNO(); 142 _PR_MD_MAP_READDIR_ERROR(err); 143 return 0; 144 } 145 if ((flags & PR_SKIP_DOT) && (de->d_name[0] == '.') && 146 (de->d_name[1] == 0)) { 147 continue; 148 } 149 if ((flags & PR_SKIP_DOT_DOT) && (de->d_name[0] == '.') && 150 (de->d_name[1] == '.') && (de->d_name[2] == 0)) { 151 continue; 152 } 153 if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.')) { 154 continue; 155 } 156 break; 157 } 158 return de->d_name; 159 } 160 161 PRInt32 _MD_delete(const char* name) { 162 PRInt32 rv, err; 163 164 rv = unlink(name); 165 if (rv == -1) { 166 err = _MD_ERRNO(); 167 _PR_MD_MAP_UNLINK_ERROR(err); 168 } 169 return (rv); 170 } 171 172 PRInt32 _MD_rename(const char* from, const char* to) { 173 PRInt32 rv = -1, err; 174 175 /* 176 ** This is trying to enforce the semantics of WINDOZE' rename 177 ** operation. That means one is not allowed to rename over top 178 ** of an existing file. Holding a lock across these two function 179 ** and the open function is known to be a bad idea, but .... 180 */ 181 if (NULL != _pr_unix_rename_lock) { 182 PR_Lock(_pr_unix_rename_lock); 183 } 184 if (0 == access(to, F_OK)) { 185 PR_SetError(PR_FILE_EXISTS_ERROR, 0); 186 } else { 187 rv = rename(from, to); 188 if (rv < 0) { 189 err = _MD_ERRNO(); 190 _PR_MD_MAP_RENAME_ERROR(err); 191 } 192 } 193 if (NULL != _pr_unix_rename_lock) { 194 PR_Unlock(_pr_unix_rename_lock); 195 } 196 return rv; 197 } 198 199 PRInt32 _MD_access(const char* name, PRAccessHow how) { 200 PRInt32 rv, err; 201 int amode; 202 203 switch (how) { 204 case PR_ACCESS_WRITE_OK: 205 amode = W_OK; 206 break; 207 case PR_ACCESS_READ_OK: 208 amode = R_OK; 209 break; 210 case PR_ACCESS_EXISTS: 211 amode = F_OK; 212 break; 213 default: 214 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 215 rv = -1; 216 goto done; 217 } 218 rv = access(name, amode); 219 220 if (rv < 0) { 221 err = _MD_ERRNO(); 222 _PR_MD_MAP_ACCESS_ERROR(err); 223 } 224 225 done: 226 return (rv); 227 } 228 229 PRInt32 _MD_mkdir(const char* name, PRIntn mode) { 230 int rv, err; 231 232 /* 233 ** This lock is used to enforce rename semantics as described 234 ** in PR_Rename. Look there for more fun details. 235 */ 236 if (NULL != _pr_unix_rename_lock) { 237 PR_Lock(_pr_unix_rename_lock); 238 } 239 rv = mkdir(name, mode); 240 if (rv < 0) { 241 err = _MD_ERRNO(); 242 _PR_MD_MAP_MKDIR_ERROR(err); 243 } 244 if (NULL != _pr_unix_rename_lock) { 245 PR_Unlock(_pr_unix_rename_lock); 246 } 247 return rv; 248 } 249 250 PRInt32 _MD_rmdir(const char* name) { 251 int rv, err; 252 253 rv = rmdir(name); 254 if (rv == -1) { 255 err = _MD_ERRNO(); 256 _PR_MD_MAP_RMDIR_ERROR(err); 257 } 258 return rv; 259 } 260 261 PRInt32 _MD_read(PRFileDesc* fd, void* buf, PRInt32 amount) { 262 PRThread* me = _PR_MD_CURRENT_THREAD(); 263 PRInt32 rv, err; 264 # ifndef _PR_USE_POLL 265 fd_set rd; 266 # else 267 struct pollfd pfd; 268 # endif /* _PR_USE_POLL */ 269 PRInt32 osfd = fd->secret->md.osfd; 270 271 # ifndef _PR_USE_POLL 272 FD_ZERO(&rd); 273 FD_SET(osfd, &rd); 274 # else 275 pfd.fd = osfd; 276 pfd.events = POLLIN; 277 # endif /* _PR_USE_POLL */ 278 while ((rv = read(osfd, buf, amount)) == -1) { 279 err = _MD_ERRNO(); 280 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 281 if (fd->secret->nonblocking) { 282 break; 283 } 284 if (!_PR_IS_NATIVE_THREAD(me)) { 285 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, 286 PR_INTERVAL_NO_TIMEOUT)) < 0) { 287 goto done; 288 } 289 } else { 290 # ifndef _PR_USE_POLL 291 while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL)) == -1 && 292 (err = _MD_ERRNO()) == EINTR) { 293 /* retry _MD_SELECT() if it is interrupted */ 294 } 295 # else /* _PR_USE_POLL */ 296 while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && 297 (err = _MD_ERRNO()) == EINTR) { 298 /* retry _MD_POLL() if it is interrupted */ 299 } 300 # endif /* _PR_USE_POLL */ 301 if (rv == -1) { 302 break; 303 } 304 } 305 if (_PR_PENDING_INTERRUPT(me)) { 306 break; 307 } 308 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 309 continue; 310 } else { 311 break; 312 } 313 } 314 if (rv < 0) { 315 if (_PR_PENDING_INTERRUPT(me)) { 316 me->flags &= ~_PR_INTERRUPT; 317 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 318 } else { 319 _PR_MD_MAP_READ_ERROR(err); 320 } 321 } 322 done: 323 return (rv); 324 } 325 326 PRInt32 _MD_write(PRFileDesc* fd, const void* buf, PRInt32 amount) { 327 PRThread* me = _PR_MD_CURRENT_THREAD(); 328 PRInt32 rv, err; 329 # ifndef _PR_USE_POLL 330 fd_set wd; 331 # else 332 struct pollfd pfd; 333 # endif /* _PR_USE_POLL */ 334 PRInt32 osfd = fd->secret->md.osfd; 335 336 # ifndef _PR_USE_POLL 337 FD_ZERO(&wd); 338 FD_SET(osfd, &wd); 339 # else 340 pfd.fd = osfd; 341 pfd.events = POLLOUT; 342 # endif /* _PR_USE_POLL */ 343 while ((rv = write(osfd, buf, amount)) == -1) { 344 err = _MD_ERRNO(); 345 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 346 if (fd->secret->nonblocking) { 347 break; 348 } 349 if (!_PR_IS_NATIVE_THREAD(me)) { 350 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, 351 PR_INTERVAL_NO_TIMEOUT)) < 0) { 352 goto done; 353 } 354 } else { 355 # ifndef _PR_USE_POLL 356 while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL)) == -1 && 357 (err = _MD_ERRNO()) == EINTR) { 358 /* retry _MD_SELECT() if it is interrupted */ 359 } 360 # else /* _PR_USE_POLL */ 361 while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && 362 (err = _MD_ERRNO()) == EINTR) { 363 /* retry _MD_POLL() if it is interrupted */ 364 } 365 # endif /* _PR_USE_POLL */ 366 if (rv == -1) { 367 break; 368 } 369 } 370 if (_PR_PENDING_INTERRUPT(me)) { 371 break; 372 } 373 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 374 continue; 375 } else { 376 break; 377 } 378 } 379 if (rv < 0) { 380 if (_PR_PENDING_INTERRUPT(me)) { 381 me->flags &= ~_PR_INTERRUPT; 382 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 383 } else { 384 _PR_MD_MAP_WRITE_ERROR(err); 385 } 386 } 387 done: 388 return (rv); 389 } 390 391 PRInt32 _MD_fsync(PRFileDesc* fd) { 392 PRInt32 rv, err; 393 394 rv = fsync(fd->secret->md.osfd); 395 if (rv == -1) { 396 err = _MD_ERRNO(); 397 _PR_MD_MAP_FSYNC_ERROR(err); 398 } 399 return (rv); 400 } 401 402 PRInt32 _MD_close(PRInt32 osfd) { 403 PRInt32 rv, err; 404 405 rv = close(osfd); 406 if (rv == -1) { 407 err = _MD_ERRNO(); 408 _PR_MD_MAP_CLOSE_ERROR(err); 409 } 410 return (rv); 411 } 412 413 PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { 414 PRInt32 osfd, err; 415 416 osfd = socket(domain, type, proto); 417 418 if (osfd == -1) { 419 err = _MD_ERRNO(); 420 _PR_MD_MAP_SOCKET_ERROR(err); 421 return (osfd); 422 } 423 424 return (osfd); 425 } 426 427 PRInt32 _MD_socketavailable(PRFileDesc* fd) { 428 PRInt32 result; 429 430 if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) { 431 _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO()); 432 return -1; 433 } 434 return result; 435 } 436 437 PRInt64 _MD_socketavailable64(PRFileDesc* fd) { 438 PRInt64 result; 439 LL_I2L(result, _MD_socketavailable(fd)); 440 return result; 441 } /* _MD_socketavailable64 */ 442 443 # define READ_FD 1 444 # define WRITE_FD 2 445 446 /* 447 * socket_io_wait -- 448 * 449 * wait for socket i/o, periodically checking for interrupt 450 * 451 * The first implementation uses select(), for platforms without 452 * poll(). The second (preferred) implementation uses poll(). 453 */ 454 455 # ifndef _PR_USE_POLL 456 457 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, 458 PRIntervalTime timeout) { 459 PRInt32 rv = -1; 460 struct timeval tv; 461 PRThread* me = _PR_MD_CURRENT_THREAD(); 462 PRIntervalTime epoch, now, elapsed, remaining; 463 PRBool wait_for_remaining; 464 PRInt32 syserror; 465 fd_set rd_wr; 466 467 switch (timeout) { 468 case PR_INTERVAL_NO_WAIT: 469 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); 470 break; 471 case PR_INTERVAL_NO_TIMEOUT: 472 /* 473 * This is a special case of the 'default' case below. 474 * Please see the comments there. 475 */ 476 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; 477 tv.tv_usec = 0; 478 FD_ZERO(&rd_wr); 479 do { 480 FD_SET(osfd, &rd_wr); 481 if (fd_type == READ_FD) { 482 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); 483 } else { 484 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); 485 } 486 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { 487 _PR_MD_MAP_SELECT_ERROR(syserror); 488 break; 489 } 490 if (_PR_PENDING_INTERRUPT(me)) { 491 me->flags &= ~_PR_INTERRUPT; 492 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 493 rv = -1; 494 break; 495 } 496 } while (rv == 0 || (rv == -1 && syserror == EINTR)); 497 break; 498 default: 499 now = epoch = PR_IntervalNow(); 500 remaining = timeout; 501 FD_ZERO(&rd_wr); 502 do { 503 /* 504 * We block in _MD_SELECT for at most 505 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, 506 * so that there is an upper limit on the delay 507 * before the interrupt bit is checked. 508 */ 509 wait_for_remaining = PR_TRUE; 510 tv.tv_sec = PR_IntervalToSeconds(remaining); 511 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { 512 wait_for_remaining = PR_FALSE; 513 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; 514 tv.tv_usec = 0; 515 } else { 516 tv.tv_usec = PR_IntervalToMicroseconds( 517 remaining - PR_SecondsToInterval(tv.tv_sec)); 518 } 519 FD_SET(osfd, &rd_wr); 520 if (fd_type == READ_FD) { 521 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); 522 } else { 523 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); 524 } 525 /* 526 * we don't consider EINTR a real error 527 */ 528 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { 529 _PR_MD_MAP_SELECT_ERROR(syserror); 530 break; 531 } 532 if (_PR_PENDING_INTERRUPT(me)) { 533 me->flags &= ~_PR_INTERRUPT; 534 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 535 rv = -1; 536 break; 537 } 538 /* 539 * We loop again if _MD_SELECT timed out or got interrupted 540 * by a signal, and the timeout deadline has not passed yet. 541 */ 542 if (rv == 0 || (rv == -1 && syserror == EINTR)) { 543 /* 544 * If _MD_SELECT timed out, we know how much time 545 * we spent in blocking, so we can avoid a 546 * PR_IntervalNow() call. 547 */ 548 if (rv == 0) { 549 if (wait_for_remaining) { 550 now += remaining; 551 } else { 552 now += PR_SecondsToInterval(tv.tv_sec) + 553 PR_MicrosecondsToInterval(tv.tv_usec); 554 } 555 } else { 556 now = PR_IntervalNow(); 557 } 558 elapsed = (PRIntervalTime)(now - epoch); 559 if (elapsed >= timeout) { 560 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); 561 rv = -1; 562 break; 563 } else { 564 remaining = timeout - elapsed; 565 } 566 } 567 } while (rv == 0 || (rv == -1 && syserror == EINTR)); 568 break; 569 } 570 return (rv); 571 } 572 573 # else /* _PR_USE_POLL */ 574 575 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, 576 PRIntervalTime timeout) { 577 PRInt32 rv = -1; 578 int msecs; 579 PRThread* me = _PR_MD_CURRENT_THREAD(); 580 PRIntervalTime epoch, now, elapsed, remaining; 581 PRBool wait_for_remaining; 582 PRInt32 syserror; 583 struct pollfd pfd; 584 585 switch (timeout) { 586 case PR_INTERVAL_NO_WAIT: 587 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); 588 break; 589 case PR_INTERVAL_NO_TIMEOUT: 590 /* 591 * This is a special case of the 'default' case below. 592 * Please see the comments there. 593 */ 594 msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; 595 pfd.fd = osfd; 596 if (fd_type == READ_FD) { 597 pfd.events = POLLIN; 598 } else { 599 pfd.events = POLLOUT; 600 } 601 do { 602 rv = _MD_POLL(&pfd, 1, msecs); 603 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { 604 _PR_MD_MAP_POLL_ERROR(syserror); 605 break; 606 } 607 /* 608 * If POLLERR is set, don't process it; retry the operation 609 */ 610 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { 611 rv = -1; 612 _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); 613 break; 614 } 615 if (_PR_PENDING_INTERRUPT(me)) { 616 me->flags &= ~_PR_INTERRUPT; 617 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 618 rv = -1; 619 break; 620 } 621 } while (rv == 0 || (rv == -1 && syserror == EINTR)); 622 break; 623 default: 624 now = epoch = PR_IntervalNow(); 625 remaining = timeout; 626 pfd.fd = osfd; 627 if (fd_type == READ_FD) { 628 pfd.events = POLLIN; 629 } else { 630 pfd.events = POLLOUT; 631 } 632 do { 633 /* 634 * We block in _MD_POLL for at most 635 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, 636 * so that there is an upper limit on the delay 637 * before the interrupt bit is checked. 638 */ 639 wait_for_remaining = PR_TRUE; 640 msecs = PR_IntervalToMilliseconds(remaining); 641 if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { 642 wait_for_remaining = PR_FALSE; 643 msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; 644 } 645 rv = _MD_POLL(&pfd, 1, msecs); 646 /* 647 * we don't consider EINTR a real error 648 */ 649 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { 650 _PR_MD_MAP_POLL_ERROR(syserror); 651 break; 652 } 653 if (_PR_PENDING_INTERRUPT(me)) { 654 me->flags &= ~_PR_INTERRUPT; 655 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 656 rv = -1; 657 break; 658 } 659 /* 660 * If POLLERR is set, don't process it; retry the operation 661 */ 662 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { 663 rv = -1; 664 _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); 665 break; 666 } 667 /* 668 * We loop again if _MD_POLL timed out or got interrupted 669 * by a signal, and the timeout deadline has not passed yet. 670 */ 671 if (rv == 0 || (rv == -1 && syserror == EINTR)) { 672 /* 673 * If _MD_POLL timed out, we know how much time 674 * we spent in blocking, so we can avoid a 675 * PR_IntervalNow() call. 676 */ 677 if (rv == 0) { 678 if (wait_for_remaining) { 679 now += remaining; 680 } else { 681 now += PR_MillisecondsToInterval(msecs); 682 } 683 } else { 684 now = PR_IntervalNow(); 685 } 686 elapsed = (PRIntervalTime)(now - epoch); 687 if (elapsed >= timeout) { 688 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); 689 rv = -1; 690 break; 691 } else { 692 remaining = timeout - elapsed; 693 } 694 } 695 } while (rv == 0 || (rv == -1 && syserror == EINTR)); 696 break; 697 } 698 return (rv); 699 } 700 701 # endif /* _PR_USE_POLL */ 702 703 static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag, 704 PRIntervalTime timeout) { 705 _PRUnixPollDesc pd; 706 PRInt32 rv; 707 708 PR_LOG(_pr_io_lm, PR_LOG_MIN, 709 ("waiting to %s on osfd=%d", 710 (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write", osfd)); 711 712 if (timeout == PR_INTERVAL_NO_WAIT) { 713 return 0; 714 } 715 716 pd.osfd = osfd; 717 pd.in_flags = wait_flag; 718 pd.out_flags = 0; 719 720 rv = _PR_WaitForMultipleFDs(&pd, 1, timeout); 721 722 if (rv == 0) { 723 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); 724 rv = -1; 725 } 726 return rv; 727 } 728 729 PRInt32 _MD_recv(PRFileDesc* fd, void* buf, PRInt32 amount, PRInt32 flags, 730 PRIntervalTime timeout) { 731 PRInt32 osfd = fd->secret->md.osfd; 732 PRInt32 rv, err; 733 PRThread* me = _PR_MD_CURRENT_THREAD(); 734 735 /* 736 * Many OS's (ex: Solaris) have a broken recv which won't read 737 * from socketpairs. As long as we don't use flags on socketpairs, this 738 * is a decent fix. - mikep 739 */ 740 # if defined(SOLARIS) 741 while ((rv = read(osfd, buf, amount)) == -1) { 742 # else 743 while ((rv = recv(osfd, buf, amount, flags)) == -1) { 744 # endif 745 err = _MD_ERRNO(); 746 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 747 if (fd->secret->nonblocking) { 748 break; 749 } 750 if (!_PR_IS_NATIVE_THREAD(me)) { 751 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) { 752 goto done; 753 } 754 } else { 755 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) { 756 goto done; 757 } 758 } 759 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 760 continue; 761 } else { 762 break; 763 } 764 } 765 if (rv < 0) { 766 _PR_MD_MAP_RECV_ERROR(err); 767 } 768 done: 769 return (rv); 770 } 771 772 PRInt32 _MD_recvfrom(PRFileDesc* fd, void* buf, PRInt32 amount, PRIntn flags, 773 PRNetAddr* addr, PRUint32* addrlen, 774 PRIntervalTime timeout) { 775 PRInt32 osfd = fd->secret->md.osfd; 776 PRInt32 rv, err; 777 PRThread* me = _PR_MD_CURRENT_THREAD(); 778 779 while ((*addrlen = PR_NETADDR_SIZE(addr)), 780 ((rv = recvfrom(osfd, buf, amount, flags, (struct sockaddr*)addr, 781 (_PRSockLen_t*)addrlen)) == -1)) { 782 err = _MD_ERRNO(); 783 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 784 if (fd->secret->nonblocking) { 785 break; 786 } 787 if (!_PR_IS_NATIVE_THREAD(me)) { 788 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) { 789 goto done; 790 } 791 } else { 792 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) { 793 goto done; 794 } 795 } 796 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 797 continue; 798 } else { 799 break; 800 } 801 } 802 if (rv < 0) { 803 _PR_MD_MAP_RECVFROM_ERROR(err); 804 } 805 done: 806 # ifdef _PR_HAVE_SOCKADDR_LEN 807 if (rv != -1) { 808 /* ignore the sa_len field of struct sockaddr */ 809 if (addr) { 810 addr->raw.family = ((struct sockaddr*)addr)->sa_family; 811 } 812 } 813 # endif /* _PR_HAVE_SOCKADDR_LEN */ 814 return (rv); 815 } 816 817 PRInt32 _MD_send(PRFileDesc* fd, const void* buf, PRInt32 amount, PRInt32 flags, 818 PRIntervalTime timeout) { 819 PRInt32 osfd = fd->secret->md.osfd; 820 PRInt32 rv, err; 821 PRThread* me = _PR_MD_CURRENT_THREAD(); 822 # if defined(SOLARIS) 823 PRInt32 tmp_amount = amount; 824 # endif 825 826 /* 827 * On pre-2.6 Solaris, send() is much slower than write(). 828 * On 2.6 and beyond, with in-kernel sockets, send() and 829 * write() are fairly equivalent in performance. 830 */ 831 # if defined(SOLARIS) 832 PR_ASSERT(0 == flags); 833 while ((rv = write(osfd, buf, tmp_amount)) == -1) { 834 # else 835 while ((rv = send(osfd, buf, amount, flags)) == -1) { 836 # endif 837 err = _MD_ERRNO(); 838 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 839 if (fd->secret->nonblocking) { 840 break; 841 } 842 if (!_PR_IS_NATIVE_THREAD(me)) { 843 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) { 844 goto done; 845 } 846 } else { 847 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) { 848 goto done; 849 } 850 } 851 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 852 continue; 853 } else { 854 # if defined(SOLARIS) 855 /* 856 * The write system call has been reported to return the ERANGE 857 * error on occasion. Try to write in smaller chunks to workaround 858 * this bug. 859 */ 860 if (err == ERANGE) { 861 if (tmp_amount > 1) { 862 tmp_amount = tmp_amount / 2; /* half the bytes */ 863 continue; 864 } 865 } 866 # endif 867 break; 868 } 869 } 870 /* 871 * optimization; if bytes sent is less than "amount" call 872 * select before returning. This is because it is likely that 873 * the next send() call will return EWOULDBLOCK. 874 */ 875 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && 876 (timeout != PR_INTERVAL_NO_WAIT)) { 877 if (_PR_IS_NATIVE_THREAD(me)) { 878 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { 879 rv = -1; 880 goto done; 881 } 882 } else { 883 if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { 884 rv = -1; 885 goto done; 886 } 887 } 888 } 889 if (rv < 0) { 890 _PR_MD_MAP_SEND_ERROR(err); 891 } 892 done: 893 return (rv); 894 } 895 896 PRInt32 _MD_sendto(PRFileDesc* fd, const void* buf, PRInt32 amount, 897 PRIntn flags, const PRNetAddr* addr, PRUint32 addrlen, 898 PRIntervalTime timeout) { 899 PRInt32 osfd = fd->secret->md.osfd; 900 PRInt32 rv, err; 901 PRThread* me = _PR_MD_CURRENT_THREAD(); 902 # ifdef _PR_HAVE_SOCKADDR_LEN 903 PRNetAddr addrCopy; 904 905 addrCopy = *addr; 906 ((struct sockaddr*)&addrCopy)->sa_len = addrlen; 907 ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; 908 909 while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr*)&addrCopy, 910 addrlen)) == -1) { 911 # else 912 while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr*)addr, 913 addrlen)) == -1) { 914 # endif 915 err = _MD_ERRNO(); 916 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 917 if (fd->secret->nonblocking) { 918 break; 919 } 920 if (!_PR_IS_NATIVE_THREAD(me)) { 921 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) { 922 goto done; 923 } 924 } else { 925 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) { 926 goto done; 927 } 928 } 929 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 930 continue; 931 } else { 932 break; 933 } 934 } 935 if (rv < 0) { 936 _PR_MD_MAP_SENDTO_ERROR(err); 937 } 938 done: 939 return (rv); 940 } 941 942 PRInt32 _MD_writev(PRFileDesc* fd, const PRIOVec* iov, PRInt32 iov_size, 943 PRIntervalTime timeout) { 944 PRInt32 rv, err; 945 PRThread* me = _PR_MD_CURRENT_THREAD(); 946 PRInt32 index, amount = 0; 947 PRInt32 osfd = fd->secret->md.osfd; 948 949 /* 950 * Calculate the total number of bytes to be sent; needed for 951 * optimization later. 952 * We could avoid this if this number was passed in; but it is 953 * probably not a big deal because iov_size is usually small (less than 954 * 3) 955 */ 956 if (!fd->secret->nonblocking) { 957 for (index = 0; index < iov_size; index++) { 958 amount += iov[index].iov_len; 959 } 960 } 961 962 while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) { 963 err = _MD_ERRNO(); 964 if ((err == EAGAIN) || (err == EWOULDBLOCK)) { 965 if (fd->secret->nonblocking) { 966 break; 967 } 968 if (!_PR_IS_NATIVE_THREAD(me)) { 969 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) { 970 goto done; 971 } 972 } else { 973 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) { 974 goto done; 975 } 976 } 977 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 978 continue; 979 } else { 980 break; 981 } 982 } 983 /* 984 * optimization; if bytes sent is less than "amount" call 985 * select before returning. This is because it is likely that 986 * the next writev() call will return EWOULDBLOCK. 987 */ 988 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && 989 (timeout != PR_INTERVAL_NO_WAIT)) { 990 if (_PR_IS_NATIVE_THREAD(me)) { 991 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { 992 rv = -1; 993 goto done; 994 } 995 } else { 996 if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { 997 rv = -1; 998 goto done; 999 } 1000 } 1001 } 1002 if (rv < 0) { 1003 _PR_MD_MAP_WRITEV_ERROR(err); 1004 } 1005 done: 1006 return (rv); 1007 } 1008 1009 PRInt32 _MD_accept(PRFileDesc* fd, PRNetAddr* addr, PRUint32* addrlen, 1010 PRIntervalTime timeout) { 1011 PRInt32 osfd = fd->secret->md.osfd; 1012 PRInt32 rv, err; 1013 PRThread* me = _PR_MD_CURRENT_THREAD(); 1014 1015 while ((rv = accept(osfd, (struct sockaddr*)addr, (_PRSockLen_t*)addrlen)) == 1016 -1) { 1017 err = _MD_ERRNO(); 1018 if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) { 1019 if (fd->secret->nonblocking) { 1020 break; 1021 } 1022 if (!_PR_IS_NATIVE_THREAD(me)) { 1023 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) { 1024 goto done; 1025 } 1026 } else { 1027 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) { 1028 goto done; 1029 } 1030 } 1031 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { 1032 continue; 1033 } else { 1034 break; 1035 } 1036 } 1037 if (rv < 0) { 1038 _PR_MD_MAP_ACCEPT_ERROR(err); 1039 } 1040 done: 1041 # ifdef _PR_HAVE_SOCKADDR_LEN 1042 if (rv != -1) { 1043 /* ignore the sa_len field of struct sockaddr */ 1044 if (addr) { 1045 addr->raw.family = ((struct sockaddr*)addr)->sa_family; 1046 } 1047 } 1048 # endif /* _PR_HAVE_SOCKADDR_LEN */ 1049 return (rv); 1050 } 1051 1052 extern int _connect(int s, const struct sockaddr* name, int namelen); 1053 PRInt32 _MD_connect(PRFileDesc* fd, const PRNetAddr* addr, PRUint32 addrlen, 1054 PRIntervalTime timeout) { 1055 PRInt32 rv, err; 1056 PRThread* me = _PR_MD_CURRENT_THREAD(); 1057 PRInt32 osfd = fd->secret->md.osfd; 1058 # ifdef _PR_HAVE_SOCKADDR_LEN 1059 PRNetAddr addrCopy; 1060 1061 addrCopy = *addr; 1062 ((struct sockaddr*)&addrCopy)->sa_len = addrlen; 1063 ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; 1064 # endif 1065 1066 /* 1067 * We initiate the connection setup by making a nonblocking connect() 1068 * call. If the connect() call fails, there are two cases we handle 1069 * specially: 1070 * 1. The connect() call was interrupted by a signal. In this case 1071 * we simply retry connect(). 1072 * 2. The NSPR socket is nonblocking and connect() fails with 1073 * EINPROGRESS. We first wait until the socket becomes writable. 1074 * Then we try to find out whether the connection setup succeeded 1075 * or failed. 1076 */ 1077 1078 retry: 1079 # ifdef _PR_HAVE_SOCKADDR_LEN 1080 if ((rv = connect(osfd, (struct sockaddr*)&addrCopy, addrlen)) == -1) { 1081 # else 1082 if ((rv = connect(osfd, (struct sockaddr*)addr, addrlen)) == -1) { 1083 # endif 1084 err = _MD_ERRNO(); 1085 1086 if (err == EINTR) { 1087 if (_PR_PENDING_INTERRUPT(me)) { 1088 me->flags &= ~_PR_INTERRUPT; 1089 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1090 return -1; 1091 } 1092 goto retry; 1093 } 1094 1095 if (!fd->secret->nonblocking && (err == EINPROGRESS)) { 1096 if (!_PR_IS_NATIVE_THREAD(me)) { 1097 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) { 1098 return -1; 1099 } 1100 } else { 1101 /* 1102 * socket_io_wait() may return -1 or 1. 1103 */ 1104 1105 rv = socket_io_wait(osfd, WRITE_FD, timeout); 1106 if (rv == -1) { 1107 return -1; 1108 } 1109 } 1110 1111 PR_ASSERT(rv == 1); 1112 if (_PR_PENDING_INTERRUPT(me)) { 1113 me->flags &= ~_PR_INTERRUPT; 1114 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1115 return -1; 1116 } 1117 err = _MD_unix_get_nonblocking_connect_error(osfd); 1118 if (err != 0) { 1119 _PR_MD_MAP_CONNECT_ERROR(err); 1120 return -1; 1121 } 1122 return 0; 1123 } 1124 1125 _PR_MD_MAP_CONNECT_ERROR(err); 1126 } 1127 1128 return rv; 1129 } /* _MD_connect */ 1130 1131 PRInt32 _MD_bind(PRFileDesc* fd, const PRNetAddr* addr, PRUint32 addrlen) { 1132 PRInt32 rv, err; 1133 # ifdef _PR_HAVE_SOCKADDR_LEN 1134 PRNetAddr addrCopy; 1135 1136 addrCopy = *addr; 1137 ((struct sockaddr*)&addrCopy)->sa_len = addrlen; 1138 ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; 1139 rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, (int)addrlen); 1140 # else 1141 rv = bind(fd->secret->md.osfd, (struct sockaddr*)addr, (int)addrlen); 1142 # endif 1143 if (rv < 0) { 1144 err = _MD_ERRNO(); 1145 _PR_MD_MAP_BIND_ERROR(err); 1146 } 1147 return (rv); 1148 } 1149 1150 PRInt32 _MD_listen(PRFileDesc* fd, PRIntn backlog) { 1151 PRInt32 rv, err; 1152 1153 rv = listen(fd->secret->md.osfd, backlog); 1154 if (rv < 0) { 1155 err = _MD_ERRNO(); 1156 _PR_MD_MAP_LISTEN_ERROR(err); 1157 } 1158 return (rv); 1159 } 1160 1161 PRInt32 _MD_shutdown(PRFileDesc* fd, PRIntn how) { 1162 PRInt32 rv, err; 1163 1164 rv = shutdown(fd->secret->md.osfd, how); 1165 if (rv < 0) { 1166 err = _MD_ERRNO(); 1167 _PR_MD_MAP_SHUTDOWN_ERROR(err); 1168 } 1169 return (rv); 1170 } 1171 1172 PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32* osfd) { 1173 PRInt32 rv, err; 1174 1175 rv = socketpair(af, type, flags, osfd); 1176 if (rv < 0) { 1177 err = _MD_ERRNO(); 1178 _PR_MD_MAP_SOCKETPAIR_ERROR(err); 1179 } 1180 return rv; 1181 } 1182 1183 PRStatus _MD_getsockname(PRFileDesc* fd, PRNetAddr* addr, PRUint32* addrlen) { 1184 PRInt32 rv, err; 1185 1186 rv = getsockname(fd->secret->md.osfd, (struct sockaddr*)addr, 1187 (_PRSockLen_t*)addrlen); 1188 # ifdef _PR_HAVE_SOCKADDR_LEN 1189 if (rv == 0) { 1190 /* ignore the sa_len field of struct sockaddr */ 1191 if (addr) { 1192 addr->raw.family = ((struct sockaddr*)addr)->sa_family; 1193 } 1194 } 1195 # endif /* _PR_HAVE_SOCKADDR_LEN */ 1196 if (rv < 0) { 1197 err = _MD_ERRNO(); 1198 _PR_MD_MAP_GETSOCKNAME_ERROR(err); 1199 } 1200 return rv == 0 ? PR_SUCCESS : PR_FAILURE; 1201 } 1202 1203 PRStatus _MD_getpeername(PRFileDesc* fd, PRNetAddr* addr, PRUint32* addrlen) { 1204 PRInt32 rv, err; 1205 1206 rv = getpeername(fd->secret->md.osfd, (struct sockaddr*)addr, 1207 (_PRSockLen_t*)addrlen); 1208 # ifdef _PR_HAVE_SOCKADDR_LEN 1209 if (rv == 0) { 1210 /* ignore the sa_len field of struct sockaddr */ 1211 if (addr) { 1212 addr->raw.family = ((struct sockaddr*)addr)->sa_family; 1213 } 1214 } 1215 # endif /* _PR_HAVE_SOCKADDR_LEN */ 1216 if (rv < 0) { 1217 err = _MD_ERRNO(); 1218 _PR_MD_MAP_GETPEERNAME_ERROR(err); 1219 } 1220 return rv == 0 ? PR_SUCCESS : PR_FAILURE; 1221 } 1222 1223 PRStatus _MD_getsockopt(PRFileDesc* fd, PRInt32 level, PRInt32 optname, 1224 char* optval, PRInt32* optlen) { 1225 PRInt32 rv, err; 1226 1227 rv = getsockopt(fd->secret->md.osfd, level, optname, optval, 1228 (_PRSockLen_t*)optlen); 1229 if (rv < 0) { 1230 err = _MD_ERRNO(); 1231 _PR_MD_MAP_GETSOCKOPT_ERROR(err); 1232 } 1233 return rv == 0 ? PR_SUCCESS : PR_FAILURE; 1234 } 1235 1236 PRStatus _MD_setsockopt(PRFileDesc* fd, PRInt32 level, PRInt32 optname, 1237 const char* optval, PRInt32 optlen) { 1238 PRInt32 rv, err; 1239 1240 rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); 1241 if (rv < 0) { 1242 err = _MD_ERRNO(); 1243 _PR_MD_MAP_SETSOCKOPT_ERROR(err); 1244 } 1245 return rv == 0 ? PR_SUCCESS : PR_FAILURE; 1246 } 1247 1248 PRStatus _MD_set_fd_inheritable(PRFileDesc* fd, PRBool inheritable) { 1249 int rv; 1250 1251 rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC); 1252 if (-1 == rv) { 1253 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); 1254 return PR_FAILURE; 1255 } 1256 return PR_SUCCESS; 1257 } 1258 1259 void _MD_init_fd_inheritable(PRFileDesc* fd, PRBool imported) { 1260 if (imported) { 1261 fd->secret->inheritable = _PR_TRI_UNKNOWN; 1262 } else { 1263 /* By default, a Unix fd is not closed on exec. */ 1264 # ifdef DEBUG 1265 { 1266 int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); 1267 PR_ASSERT(0 == flags); 1268 } 1269 # endif 1270 fd->secret->inheritable = _PR_TRI_TRUE; 1271 } 1272 } 1273 1274 /************************************************************************/ 1275 # if !defined(_PR_USE_POLL) 1276 1277 /* 1278 ** Scan through io queue and find any bad fd's that triggered the error 1279 ** from _MD_SELECT 1280 */ 1281 static void FindBadFDs(void) { 1282 PRCList* q; 1283 PRThread* me = _MD_CURRENT_THREAD(); 1284 1285 PR_ASSERT(!_PR_IS_NATIVE_THREAD(me)); 1286 q = (_PR_IOQ(me->cpu)).next; 1287 _PR_IOQ_MAX_OSFD(me->cpu) = -1; 1288 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; 1289 while (q != &_PR_IOQ(me->cpu)) { 1290 PRPollQueue* pq = _PR_POLLQUEUE_PTR(q); 1291 PRBool notify = PR_FALSE; 1292 _PRUnixPollDesc* pds = pq->pds; 1293 _PRUnixPollDesc* epds = pds + pq->npds; 1294 PRInt32 pq_max_osfd = -1; 1295 1296 q = q->next; 1297 for (; pds < epds; pds++) { 1298 PRInt32 osfd = pds->osfd; 1299 pds->out_flags = 0; 1300 PR_ASSERT(osfd >= 0 || pds->in_flags == 0); 1301 if (pds->in_flags == 0) { 1302 continue; /* skip this fd */ 1303 } 1304 if (fcntl(osfd, F_GETFL, 0) == -1) { 1305 /* Found a bad descriptor, remove it from the fd_sets. */ 1306 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("file descriptor %d is bad", osfd)); 1307 pds->out_flags = _PR_UNIX_POLL_NVAL; 1308 notify = PR_TRUE; 1309 } 1310 if (osfd > pq_max_osfd) { 1311 pq_max_osfd = osfd; 1312 } 1313 } 1314 1315 if (notify) { 1316 PRIntn pri; 1317 PR_REMOVE_LINK(&pq->links); 1318 pq->on_ioq = PR_FALSE; 1319 1320 /* 1321 * Decrement the count of descriptors for each desciptor/event 1322 * because this I/O request is being removed from the 1323 * ioq 1324 */ 1325 pds = pq->pds; 1326 for (; pds < epds; pds++) { 1327 PRInt32 osfd = pds->osfd; 1328 PRInt16 in_flags = pds->in_flags; 1329 PR_ASSERT(osfd >= 0 || in_flags == 0); 1330 if (in_flags & _PR_UNIX_POLL_READ) { 1331 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) { 1332 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); 1333 } 1334 } 1335 if (in_flags & _PR_UNIX_POLL_WRITE) { 1336 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) { 1337 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); 1338 } 1339 } 1340 if (in_flags & _PR_UNIX_POLL_EXCEPT) { 1341 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) { 1342 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); 1343 } 1344 } 1345 } 1346 1347 _PR_THREAD_LOCK(pq->thr); 1348 if (pq->thr->flags & (_PR_ON_PAUSEQ | _PR_ON_SLEEPQ)) { 1349 _PRCPU* cpu = pq->thr->cpu; 1350 _PR_SLEEPQ_LOCK(pq->thr->cpu); 1351 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); 1352 _PR_SLEEPQ_UNLOCK(pq->thr->cpu); 1353 1354 if (pq->thr->flags & _PR_SUSPENDING) { 1355 /* 1356 * set thread state to SUSPENDED; 1357 * a Resume operation on the thread 1358 * will move it to the runQ 1359 */ 1360 pq->thr->state = _PR_SUSPENDED; 1361 _PR_MISCQ_LOCK(pq->thr->cpu); 1362 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); 1363 _PR_MISCQ_UNLOCK(pq->thr->cpu); 1364 } else { 1365 pri = pq->thr->priority; 1366 pq->thr->state = _PR_RUNNABLE; 1367 1368 _PR_RUNQ_LOCK(cpu); 1369 _PR_ADD_RUNQ(pq->thr, cpu, pri); 1370 _PR_RUNQ_UNLOCK(cpu); 1371 } 1372 } 1373 _PR_THREAD_UNLOCK(pq->thr); 1374 } else { 1375 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) { 1376 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; 1377 } 1378 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) { 1379 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; 1380 } 1381 } 1382 } 1383 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1384 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) { 1385 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; 1386 } 1387 } 1388 } 1389 # endif /* !defined(_PR_USE_POLL) */ 1390 1391 /************************************************************************/ 1392 1393 /* 1394 ** Called by the scheduler when there is nothing to do. This means that 1395 ** all threads are blocked on some monitor somewhere. 1396 ** 1397 ** Note: this code doesn't release the scheduler lock. 1398 */ 1399 /* 1400 ** Pause the current CPU. longjmp to the cpu's pause stack 1401 ** 1402 ** This must be called with the scheduler locked 1403 */ 1404 void _MD_PauseCPU(PRIntervalTime ticks) { 1405 PRThread* me = _MD_CURRENT_THREAD(); 1406 # ifdef _PR_USE_POLL 1407 int timeout; 1408 struct pollfd* pollfds; /* an array of pollfd structures */ 1409 struct pollfd* pollfdPtr; /* a pointer that steps through the array */ 1410 unsigned long npollfds; /* number of pollfd structures in array */ 1411 unsigned long pollfds_size; 1412 int nfd; /* to hold the return value of poll() */ 1413 # else 1414 struct timeval timeout, *tvp; 1415 fd_set r, w, e; 1416 fd_set *rp, *wp, *ep; 1417 PRInt32 max_osfd, nfd; 1418 # endif /* _PR_USE_POLL */ 1419 PRInt32 rv; 1420 PRCList* q; 1421 PRUint32 min_timeout; 1422 sigset_t oldset; 1423 1424 PR_ASSERT(_PR_MD_GET_INTSOFF() != 0); 1425 1426 _PR_MD_IOQ_LOCK(); 1427 1428 # ifdef _PR_USE_POLL 1429 /* Build up the pollfd structure array to wait on */ 1430 1431 /* Find out how many pollfd structures are needed */ 1432 npollfds = _PR_IOQ_OSFD_CNT(me->cpu); 1433 PR_ASSERT(npollfds >= 0); 1434 1435 /* 1436 * We use a pipe to wake up a native thread. An fd is needed 1437 * for the pipe and we poll it for reading. 1438 */ 1439 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1440 npollfds++; 1441 } 1442 1443 /* 1444 * if the cpu's pollfd array is not big enough, release it and allocate a new 1445 * one 1446 */ 1447 if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) { 1448 if (_PR_IOQ_POLLFDS(me->cpu) != NULL) { 1449 PR_DELETE(_PR_IOQ_POLLFDS(me->cpu)); 1450 } 1451 pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds); 1452 pollfds = (struct pollfd*)PR_MALLOC(pollfds_size * sizeof(struct pollfd)); 1453 _PR_IOQ_POLLFDS(me->cpu) = pollfds; 1454 _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size; 1455 } else { 1456 pollfds = _PR_IOQ_POLLFDS(me->cpu); 1457 } 1458 pollfdPtr = pollfds; 1459 1460 /* 1461 * If we need to poll the pipe for waking up a native thread, 1462 * the pipe's fd is the first element in the pollfds array. 1463 */ 1464 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1465 pollfdPtr->fd = _pr_md_pipefd[0]; 1466 pollfdPtr->events = POLLIN; 1467 pollfdPtr++; 1468 } 1469 1470 min_timeout = PR_INTERVAL_NO_TIMEOUT; 1471 for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) { 1472 PRPollQueue* pq = _PR_POLLQUEUE_PTR(q); 1473 _PRUnixPollDesc* pds = pq->pds; 1474 _PRUnixPollDesc* epds = pds + pq->npds; 1475 1476 if (pq->timeout < min_timeout) { 1477 min_timeout = pq->timeout; 1478 } 1479 for (; pds < epds; pds++, pollfdPtr++) { 1480 /* 1481 * Assert that the pollfdPtr pointer does not go 1482 * beyond the end of the pollfds array 1483 */ 1484 PR_ASSERT(pollfdPtr < pollfds + npollfds); 1485 pollfdPtr->fd = pds->osfd; 1486 /* direct copy of poll flags */ 1487 pollfdPtr->events = pds->in_flags; 1488 } 1489 } 1490 _PR_IOQ_TIMEOUT(me->cpu) = min_timeout; 1491 # else 1492 /* 1493 * assigment of fd_sets 1494 */ 1495 r = _PR_FD_READ_SET(me->cpu); 1496 w = _PR_FD_WRITE_SET(me->cpu); 1497 e = _PR_FD_EXCEPTION_SET(me->cpu); 1498 1499 rp = &r; 1500 wp = &w; 1501 ep = &e; 1502 1503 max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1; 1504 min_timeout = _PR_IOQ_TIMEOUT(me->cpu); 1505 # endif /* _PR_USE_POLL */ 1506 /* 1507 ** Compute the minimum timeout value: make it the smaller of the 1508 ** timeouts specified by the i/o pollers or the timeout of the first 1509 ** sleeping thread. 1510 */ 1511 q = _PR_SLEEPQ(me->cpu).next; 1512 1513 if (q != &_PR_SLEEPQ(me->cpu)) { 1514 PRThread* t = _PR_THREAD_PTR(q); 1515 1516 if (t->sleep < min_timeout) { 1517 min_timeout = t->sleep; 1518 } 1519 } 1520 if (min_timeout > ticks) { 1521 min_timeout = ticks; 1522 } 1523 1524 # ifdef _PR_USE_POLL 1525 if (min_timeout == PR_INTERVAL_NO_TIMEOUT) { 1526 timeout = -1; 1527 } else { 1528 timeout = PR_IntervalToMilliseconds(min_timeout); 1529 } 1530 # else 1531 if (min_timeout == PR_INTERVAL_NO_TIMEOUT) { 1532 tvp = NULL; 1533 } else { 1534 timeout.tv_sec = PR_IntervalToSeconds(min_timeout); 1535 timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout) % PR_USEC_PER_SEC; 1536 tvp = &timeout; 1537 } 1538 # endif /* _PR_USE_POLL */ 1539 1540 _PR_MD_IOQ_UNLOCK(); 1541 _MD_CHECK_FOR_EXIT(); 1542 /* 1543 * check for i/o operations 1544 */ 1545 # ifndef _PR_NO_CLOCK_TIMER 1546 /* 1547 * Disable the clock interrupts while we are in select, if clock interrupts 1548 * are enabled. Otherwise, when the select/poll calls are interrupted, the 1549 * timer value starts ticking from zero again when the system call is 1550 * restarted. 1551 */ 1552 if (!_nspr_noclock) { 1553 PR_ASSERT(sigismember(&timer_set, SIGALRM)); 1554 } 1555 sigprocmask(SIG_BLOCK, &timer_set, &oldset); 1556 # endif /* !_PR_NO_CLOCK_TIMER */ 1557 1558 # ifndef _PR_USE_POLL 1559 PR_ASSERT(FD_ISSET(_pr_md_pipefd[0], rp)); 1560 nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp); 1561 # else 1562 nfd = _MD_POLL(pollfds, npollfds, timeout); 1563 # endif /* !_PR_USE_POLL */ 1564 1565 # ifndef _PR_NO_CLOCK_TIMER 1566 if (!_nspr_noclock) { 1567 sigprocmask(SIG_SETMASK, &oldset, 0); 1568 } 1569 # endif /* !_PR_NO_CLOCK_TIMER */ 1570 1571 _MD_CHECK_FOR_EXIT(); 1572 1573 _PR_MD_primordial_cpu(); 1574 1575 _PR_MD_IOQ_LOCK(); 1576 /* 1577 ** Notify monitors that are associated with the selected descriptors. 1578 */ 1579 # ifdef _PR_USE_POLL 1580 if (nfd > 0) { 1581 pollfdPtr = pollfds; 1582 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1583 /* 1584 * Assert that the pipe is the first element in the 1585 * pollfds array. 1586 */ 1587 PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]); 1588 if ((pollfds[0].revents & POLLIN) && (nfd == 1)) { 1589 /* 1590 * woken up by another thread; read all the data 1591 * in the pipe to empty the pipe 1592 */ 1593 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == 1594 PIPE_BUF) { 1595 } 1596 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); 1597 } 1598 pollfdPtr++; 1599 } 1600 for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) { 1601 PRPollQueue* pq = _PR_POLLQUEUE_PTR(q); 1602 PRBool notify = PR_FALSE; 1603 _PRUnixPollDesc* pds = pq->pds; 1604 _PRUnixPollDesc* epds = pds + pq->npds; 1605 1606 for (; pds < epds; pds++, pollfdPtr++) { 1607 /* 1608 * Assert that the pollfdPtr pointer does not go beyond 1609 * the end of the pollfds array. 1610 */ 1611 PR_ASSERT(pollfdPtr < pollfds + npollfds); 1612 /* 1613 * Assert that the fd's in the pollfds array (stepped 1614 * through by pollfdPtr) are in the same order as 1615 * the fd's in _PR_IOQ() (stepped through by q and pds). 1616 * This is how the pollfds array was created earlier. 1617 */ 1618 PR_ASSERT(pollfdPtr->fd == pds->osfd); 1619 pds->out_flags = pollfdPtr->revents; 1620 /* Negative fd's are ignored by poll() */ 1621 if (pds->osfd >= 0 && pds->out_flags) { 1622 notify = PR_TRUE; 1623 } 1624 } 1625 if (notify) { 1626 PRIntn pri; 1627 PRThread* thred; 1628 1629 PR_REMOVE_LINK(&pq->links); 1630 pq->on_ioq = PR_FALSE; 1631 1632 thred = pq->thr; 1633 _PR_THREAD_LOCK(thred); 1634 if (pq->thr->flags & (_PR_ON_PAUSEQ | _PR_ON_SLEEPQ)) { 1635 _PRCPU* cpu = pq->thr->cpu; 1636 _PR_SLEEPQ_LOCK(pq->thr->cpu); 1637 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); 1638 _PR_SLEEPQ_UNLOCK(pq->thr->cpu); 1639 1640 if (pq->thr->flags & _PR_SUSPENDING) { 1641 /* 1642 * set thread state to SUSPENDED; 1643 * a Resume operation on the thread 1644 * will move it to the runQ 1645 */ 1646 pq->thr->state = _PR_SUSPENDED; 1647 _PR_MISCQ_LOCK(pq->thr->cpu); 1648 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); 1649 _PR_MISCQ_UNLOCK(pq->thr->cpu); 1650 } else { 1651 pri = pq->thr->priority; 1652 pq->thr->state = _PR_RUNNABLE; 1653 1654 _PR_RUNQ_LOCK(cpu); 1655 _PR_ADD_RUNQ(pq->thr, cpu, pri); 1656 _PR_RUNQ_UNLOCK(cpu); 1657 if (_pr_md_idle_cpus > 1) { 1658 _PR_MD_WAKEUP_WAITER(thred); 1659 } 1660 } 1661 } 1662 _PR_THREAD_UNLOCK(thred); 1663 _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds; 1664 PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0); 1665 } 1666 } 1667 } else if (nfd == -1) { 1668 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno)); 1669 } 1670 1671 # else 1672 if (nfd > 0) { 1673 q = _PR_IOQ(me->cpu).next; 1674 _PR_IOQ_MAX_OSFD(me->cpu) = -1; 1675 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; 1676 while (q != &_PR_IOQ(me->cpu)) { 1677 PRPollQueue* pq = _PR_POLLQUEUE_PTR(q); 1678 PRBool notify = PR_FALSE; 1679 _PRUnixPollDesc* pds = pq->pds; 1680 _PRUnixPollDesc* epds = pds + pq->npds; 1681 PRInt32 pq_max_osfd = -1; 1682 1683 q = q->next; 1684 for (; pds < epds; pds++) { 1685 PRInt32 osfd = pds->osfd; 1686 PRInt16 in_flags = pds->in_flags; 1687 PRInt16 out_flags = 0; 1688 PR_ASSERT(osfd >= 0 || in_flags == 0); 1689 if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) { 1690 out_flags |= _PR_UNIX_POLL_READ; 1691 } 1692 if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) { 1693 out_flags |= _PR_UNIX_POLL_WRITE; 1694 } 1695 if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) { 1696 out_flags |= _PR_UNIX_POLL_EXCEPT; 1697 } 1698 pds->out_flags = out_flags; 1699 if (out_flags) { 1700 notify = PR_TRUE; 1701 } 1702 if (osfd > pq_max_osfd) { 1703 pq_max_osfd = osfd; 1704 } 1705 } 1706 if (notify == PR_TRUE) { 1707 PRIntn pri; 1708 PRThread* thred; 1709 1710 PR_REMOVE_LINK(&pq->links); 1711 pq->on_ioq = PR_FALSE; 1712 1713 /* 1714 * Decrement the count of descriptors for each desciptor/event 1715 * because this I/O request is being removed from the 1716 * ioq 1717 */ 1718 pds = pq->pds; 1719 for (; pds < epds; pds++) { 1720 PRInt32 osfd = pds->osfd; 1721 PRInt16 in_flags = pds->in_flags; 1722 PR_ASSERT(osfd >= 0 || in_flags == 0); 1723 if (in_flags & _PR_UNIX_POLL_READ) { 1724 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) { 1725 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); 1726 } 1727 } 1728 if (in_flags & _PR_UNIX_POLL_WRITE) { 1729 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) { 1730 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); 1731 } 1732 } 1733 if (in_flags & _PR_UNIX_POLL_EXCEPT) { 1734 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) { 1735 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); 1736 } 1737 } 1738 } 1739 1740 /* 1741 * Because this thread can run on a different cpu right 1742 * after being added to the run queue, do not dereference 1743 * pq 1744 */ 1745 thred = pq->thr; 1746 _PR_THREAD_LOCK(thred); 1747 if (pq->thr->flags & (_PR_ON_PAUSEQ | _PR_ON_SLEEPQ)) { 1748 _PRCPU* cpu = thred->cpu; 1749 _PR_SLEEPQ_LOCK(pq->thr->cpu); 1750 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); 1751 _PR_SLEEPQ_UNLOCK(pq->thr->cpu); 1752 1753 if (pq->thr->flags & _PR_SUSPENDING) { 1754 /* 1755 * set thread state to SUSPENDED; 1756 * a Resume operation on the thread 1757 * will move it to the runQ 1758 */ 1759 pq->thr->state = _PR_SUSPENDED; 1760 _PR_MISCQ_LOCK(pq->thr->cpu); 1761 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); 1762 _PR_MISCQ_UNLOCK(pq->thr->cpu); 1763 } else { 1764 pri = pq->thr->priority; 1765 pq->thr->state = _PR_RUNNABLE; 1766 1767 pq->thr->cpu = cpu; 1768 _PR_RUNQ_LOCK(cpu); 1769 _PR_ADD_RUNQ(pq->thr, cpu, pri); 1770 _PR_RUNQ_UNLOCK(cpu); 1771 if (_pr_md_idle_cpus > 1) { 1772 _PR_MD_WAKEUP_WAITER(thred); 1773 } 1774 } 1775 } 1776 _PR_THREAD_UNLOCK(thred); 1777 } else { 1778 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) { 1779 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; 1780 } 1781 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) { 1782 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; 1783 } 1784 } 1785 } 1786 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1787 if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) { 1788 /* 1789 * woken up by another thread; read all the data 1790 * in the pipe to empty the pipe 1791 */ 1792 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == 1793 PIPE_BUF) { 1794 } 1795 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); 1796 } 1797 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) { 1798 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; 1799 } 1800 } 1801 } else if (nfd < 0) { 1802 if (errno == EBADF) { 1803 FindBadFDs(); 1804 } else { 1805 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d", errno)); 1806 } 1807 } else { 1808 PR_ASSERT(nfd == 0); 1809 /* 1810 * compute the new value of _PR_IOQ_TIMEOUT 1811 */ 1812 q = _PR_IOQ(me->cpu).next; 1813 _PR_IOQ_MAX_OSFD(me->cpu) = -1; 1814 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; 1815 while (q != &_PR_IOQ(me->cpu)) { 1816 PRPollQueue* pq = _PR_POLLQUEUE_PTR(q); 1817 _PRUnixPollDesc* pds = pq->pds; 1818 _PRUnixPollDesc* epds = pds + pq->npds; 1819 PRInt32 pq_max_osfd = -1; 1820 1821 q = q->next; 1822 for (; pds < epds; pds++) { 1823 if (pds->osfd > pq_max_osfd) { 1824 pq_max_osfd = pds->osfd; 1825 } 1826 } 1827 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) { 1828 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; 1829 } 1830 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) { 1831 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; 1832 } 1833 } 1834 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { 1835 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) { 1836 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; 1837 } 1838 } 1839 } 1840 # endif /* _PR_USE_POLL */ 1841 _PR_MD_IOQ_UNLOCK(); 1842 } 1843 1844 void _MD_Wakeup_CPUs() { 1845 PRInt32 rv, data; 1846 1847 data = 0; 1848 rv = write(_pr_md_pipefd[1], &data, 1); 1849 1850 while ((rv < 0) && (errno == EAGAIN)) { 1851 /* 1852 * pipe full, read all data in pipe to empty it 1853 */ 1854 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == 1855 PIPE_BUF) { 1856 } 1857 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); 1858 rv = write(_pr_md_pipefd[1], &data, 1); 1859 } 1860 } 1861 1862 void _MD_InitCPUS() { 1863 PRInt32 rv, flags; 1864 PRThread* me = _MD_CURRENT_THREAD(); 1865 1866 rv = pipe(_pr_md_pipefd); 1867 PR_ASSERT(rv == 0); 1868 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; 1869 # ifndef _PR_USE_POLL 1870 FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu)); 1871 # endif 1872 1873 flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0); 1874 fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK); 1875 flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0); 1876 fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK); 1877 } 1878 1879 /* 1880 ** Unix SIGALRM (clock) signal handler 1881 */ 1882 static void ClockInterruptHandler() { 1883 int olderrno; 1884 PRUintn pri; 1885 _PRCPU* cpu = _PR_MD_CURRENT_CPU(); 1886 PRThread* me = _MD_CURRENT_THREAD(); 1887 1888 # ifdef SOLARIS 1889 if (!me || _PR_IS_NATIVE_THREAD(me)) { 1890 _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK; 1891 return; 1892 } 1893 # endif 1894 1895 if (_PR_MD_GET_INTSOFF() != 0) { 1896 cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK; 1897 return; 1898 } 1899 _PR_MD_SET_INTSOFF(1); 1900 1901 olderrno = errno; 1902 _PR_ClockInterrupt(); 1903 errno = olderrno; 1904 1905 /* 1906 ** If the interrupt wants a resched or if some other thread at 1907 ** the same priority needs the cpu, reschedule. 1908 */ 1909 pri = me->priority; 1910 if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) { 1911 # ifdef _PR_NO_PREEMPT 1912 cpu->resched = PR_TRUE; 1913 if (pr_interruptSwitchHook) { 1914 (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg); 1915 } 1916 # else /* _PR_NO_PREEMPT */ 1917 /* 1918 ** Re-enable unix interrupts (so that we can use 1919 ** setjmp/longjmp for context switching without having to 1920 ** worry about the signal state) 1921 */ 1922 sigprocmask(SIG_SETMASK, &empty_set, 0); 1923 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch")); 1924 1925 if (!(me->flags & _PR_IDLE_THREAD)) { 1926 _PR_THREAD_LOCK(me); 1927 me->state = _PR_RUNNABLE; 1928 me->cpu = cpu; 1929 _PR_RUNQ_LOCK(cpu); 1930 _PR_ADD_RUNQ(me, cpu, pri); 1931 _PR_RUNQ_UNLOCK(cpu); 1932 _PR_THREAD_UNLOCK(me); 1933 } else { 1934 me->state = _PR_RUNNABLE; 1935 } 1936 _MD_SWITCH_CONTEXT(me); 1937 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch")); 1938 # endif /* _PR_NO_PREEMPT */ 1939 } 1940 /* 1941 * Because this thread could be running on a different cpu after 1942 * a context switch the current cpu should be accessed and the 1943 * value of the 'cpu' variable should not be used. 1944 */ 1945 _PR_MD_SET_INTSOFF(0); 1946 } 1947 1948 /* # of milliseconds per clock tick that we will use */ 1949 # define MSEC_PER_TICK 50 1950 1951 void _MD_StartInterrupts() { 1952 char* eval; 1953 1954 if ((eval = getenv("NSPR_NOCLOCK")) != NULL) { 1955 if (atoi(eval) == 0) { 1956 _nspr_noclock = 0; 1957 } else { 1958 _nspr_noclock = 1; 1959 } 1960 } 1961 1962 # ifndef _PR_NO_CLOCK_TIMER 1963 if (!_nspr_noclock) { 1964 _MD_EnableClockInterrupts(); 1965 } 1966 # endif 1967 } 1968 1969 void _MD_StopInterrupts() { sigprocmask(SIG_BLOCK, &timer_set, 0); } 1970 1971 void _MD_EnableClockInterrupts() { 1972 struct itimerval itval; 1973 extern PRUintn _pr_numCPU; 1974 struct sigaction vtact; 1975 1976 vtact.sa_handler = (void (*)())ClockInterruptHandler; 1977 sigemptyset(&vtact.sa_mask); 1978 vtact.sa_flags = SA_RESTART; 1979 sigaction(SIGALRM, &vtact, 0); 1980 1981 PR_ASSERT(_pr_numCPU == 1); 1982 itval.it_interval.tv_sec = 0; 1983 itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC; 1984 itval.it_value = itval.it_interval; 1985 setitimer(ITIMER_REAL, &itval, 0); 1986 } 1987 1988 void _MD_DisableClockInterrupts() { 1989 struct itimerval itval; 1990 extern PRUintn _pr_numCPU; 1991 1992 PR_ASSERT(_pr_numCPU == 1); 1993 itval.it_interval.tv_sec = 0; 1994 itval.it_interval.tv_usec = 0; 1995 itval.it_value = itval.it_interval; 1996 setitimer(ITIMER_REAL, &itval, 0); 1997 } 1998 1999 void _MD_BlockClockInterrupts() { sigprocmask(SIG_BLOCK, &timer_set, 0); } 2000 2001 void _MD_UnblockClockInterrupts() { sigprocmask(SIG_UNBLOCK, &timer_set, 0); } 2002 2003 void _MD_MakeNonblock(PRFileDesc* fd) { 2004 PRInt32 osfd = fd->secret->md.osfd; 2005 int flags; 2006 2007 if (osfd <= 2) { 2008 /* Don't mess around with stdin, stdout or stderr */ 2009 return; 2010 } 2011 flags = fcntl(osfd, F_GETFL, 0); 2012 2013 /* 2014 * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible. 2015 * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O), 2016 * otherwise connect() still blocks and can be interrupted by SIGALRM. 2017 */ 2018 2019 fcntl(osfd, F_SETFL, flags | O_NONBLOCK); 2020 } 2021 2022 PRInt32 _MD_open(const char* name, PRIntn flags, PRIntn mode) { 2023 PRInt32 osflags; 2024 PRInt32 rv, err; 2025 2026 if (flags & PR_RDWR) { 2027 osflags = O_RDWR; 2028 } else if (flags & PR_WRONLY) { 2029 osflags = O_WRONLY; 2030 } else { 2031 osflags = O_RDONLY; 2032 } 2033 2034 if (flags & PR_EXCL) { 2035 osflags |= O_EXCL; 2036 } 2037 if (flags & PR_APPEND) { 2038 osflags |= O_APPEND; 2039 } 2040 if (flags & PR_TRUNCATE) { 2041 osflags |= O_TRUNC; 2042 } 2043 if (flags & PR_SYNC) { 2044 # if defined(O_SYNC) 2045 osflags |= O_SYNC; 2046 # elif defined(O_FSYNC) 2047 osflags |= O_FSYNC; 2048 # else 2049 # error "Neither O_SYNC nor O_FSYNC is defined on this platform" 2050 # endif 2051 } 2052 2053 /* 2054 ** On creations we hold the 'create' lock in order to enforce 2055 ** the semantics of PR_Rename. (see the latter for more details) 2056 */ 2057 if (flags & PR_CREATE_FILE) { 2058 osflags |= O_CREAT; 2059 if (NULL != _pr_unix_rename_lock) { 2060 PR_Lock(_pr_unix_rename_lock); 2061 } 2062 } 2063 2064 # if defined(ANDROID) 2065 osflags |= O_LARGEFILE; 2066 # endif 2067 2068 rv = _md_iovector._open64(name, osflags, mode); 2069 2070 if (rv < 0) { 2071 err = _MD_ERRNO(); 2072 _PR_MD_MAP_OPEN_ERROR(err); 2073 } 2074 2075 if ((flags & PR_CREATE_FILE) && (NULL != _pr_unix_rename_lock)) { 2076 PR_Unlock(_pr_unix_rename_lock); 2077 } 2078 return rv; 2079 } 2080 2081 PRIntervalTime intr_timeout_ticks; 2082 2083 # if defined(SOLARIS) 2084 static void sigsegvhandler() { 2085 fprintf(stderr, "Received SIGSEGV\n"); 2086 fflush(stderr); 2087 pause(); 2088 } 2089 2090 static void sigaborthandler() { 2091 fprintf(stderr, "Received SIGABRT\n"); 2092 fflush(stderr); 2093 pause(); 2094 } 2095 2096 static void sigbushandler() { 2097 fprintf(stderr, "Received SIGBUS\n"); 2098 fflush(stderr); 2099 pause(); 2100 } 2101 # endif /* SOLARIS */ 2102 2103 #endif /* !defined(_PR_PTHREADS) */ 2104 2105 void _MD_query_fd_inheritable(PRFileDesc* fd) { 2106 int flags; 2107 2108 PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); 2109 flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); 2110 PR_ASSERT(-1 != flags); 2111 fd->secret->inheritable = (flags & FD_CLOEXEC) ? _PR_TRI_FALSE : _PR_TRI_TRUE; 2112 } 2113 2114 PROffset32 _MD_lseek(PRFileDesc* fd, PROffset32 offset, PRSeekWhence whence) { 2115 PROffset32 rv, where; 2116 2117 switch (whence) { 2118 case PR_SEEK_SET: 2119 where = SEEK_SET; 2120 break; 2121 case PR_SEEK_CUR: 2122 where = SEEK_CUR; 2123 break; 2124 case PR_SEEK_END: 2125 where = SEEK_END; 2126 break; 2127 default: 2128 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 2129 rv = -1; 2130 goto done; 2131 } 2132 rv = lseek(fd->secret->md.osfd, offset, where); 2133 if (rv == -1) { 2134 PRInt32 syserr = _MD_ERRNO(); 2135 _PR_MD_MAP_LSEEK_ERROR(syserr); 2136 } 2137 done: 2138 return (rv); 2139 } 2140 2141 PROffset64 _MD_lseek64(PRFileDesc* fd, PROffset64 offset, PRSeekWhence whence) { 2142 PRInt32 where; 2143 PROffset64 rv; 2144 2145 switch (whence) { 2146 case PR_SEEK_SET: 2147 where = SEEK_SET; 2148 break; 2149 case PR_SEEK_CUR: 2150 where = SEEK_CUR; 2151 break; 2152 case PR_SEEK_END: 2153 where = SEEK_END; 2154 break; 2155 default: 2156 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 2157 rv = minus_one; 2158 goto done; 2159 } 2160 rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where); 2161 if (LL_EQ(rv, minus_one)) { 2162 PRInt32 syserr = _MD_ERRNO(); 2163 _PR_MD_MAP_LSEEK_ERROR(syserr); 2164 } 2165 done: 2166 return rv; 2167 } /* _MD_lseek64 */ 2168 2169 /* 2170 ** _MD_set_fileinfo_times -- 2171 ** Set the modifyTime and creationTime of the PRFileInfo 2172 ** structure using the values in struct stat. 2173 ** 2174 ** _MD_set_fileinfo64_times -- 2175 ** Set the modifyTime and creationTime of the PRFileInfo64 2176 ** structure using the values in _MDStat64. 2177 */ 2178 2179 #if defined(_PR_STAT_HAS_ST_ATIM) 2180 /* 2181 ** struct stat has st_atim, st_mtim, and st_ctim fields of 2182 ** type timestruc_t. 2183 */ 2184 static void _MD_set_fileinfo_times(const struct stat* sb, PRFileInfo* info) { 2185 PRInt64 us, s2us; 2186 2187 LL_I2L(s2us, PR_USEC_PER_SEC); 2188 LL_I2L(info->modifyTime, sb->st_mtim.tv_sec); 2189 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2190 LL_I2L(us, sb->st_mtim.tv_nsec / 1000); 2191 LL_ADD(info->modifyTime, info->modifyTime, us); 2192 LL_I2L(info->creationTime, sb->st_ctim.tv_sec); 2193 LL_MUL(info->creationTime, info->creationTime, s2us); 2194 LL_I2L(us, sb->st_ctim.tv_nsec / 1000); 2195 LL_ADD(info->creationTime, info->creationTime, us); 2196 } 2197 2198 static void _MD_set_fileinfo64_times(const _MDStat64* sb, PRFileInfo64* info) { 2199 PRInt64 us, s2us; 2200 2201 LL_I2L(s2us, PR_USEC_PER_SEC); 2202 LL_I2L(info->modifyTime, sb->st_mtim.tv_sec); 2203 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2204 LL_I2L(us, sb->st_mtim.tv_nsec / 1000); 2205 LL_ADD(info->modifyTime, info->modifyTime, us); 2206 LL_I2L(info->creationTime, sb->st_ctim.tv_sec); 2207 LL_MUL(info->creationTime, info->creationTime, s2us); 2208 LL_I2L(us, sb->st_ctim.tv_nsec / 1000); 2209 LL_ADD(info->creationTime, info->creationTime, us); 2210 } 2211 #elif defined(_PR_STAT_HAS_ST_ATIM_UNION) 2212 /* 2213 ** The st_atim, st_mtim, and st_ctim fields in struct stat are 2214 ** unions with a st__tim union member of type timestruc_t. 2215 */ 2216 static void _MD_set_fileinfo_times(const struct stat* sb, PRFileInfo* info) { 2217 PRInt64 us, s2us; 2218 2219 LL_I2L(s2us, PR_USEC_PER_SEC); 2220 LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec); 2221 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2222 LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000); 2223 LL_ADD(info->modifyTime, info->modifyTime, us); 2224 LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec); 2225 LL_MUL(info->creationTime, info->creationTime, s2us); 2226 LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000); 2227 LL_ADD(info->creationTime, info->creationTime, us); 2228 } 2229 2230 static void _MD_set_fileinfo64_times(const _MDStat64* sb, PRFileInfo64* info) { 2231 PRInt64 us, s2us; 2232 2233 LL_I2L(s2us, PR_USEC_PER_SEC); 2234 LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec); 2235 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2236 LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000); 2237 LL_ADD(info->modifyTime, info->modifyTime, us); 2238 LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec); 2239 LL_MUL(info->creationTime, info->creationTime, s2us); 2240 LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000); 2241 LL_ADD(info->creationTime, info->creationTime, us); 2242 } 2243 #elif defined(_PR_STAT_HAS_ST_ATIMESPEC) 2244 /* 2245 ** struct stat has st_atimespec, st_mtimespec, and st_ctimespec 2246 ** fields of type struct timespec. 2247 */ 2248 # if defined(_PR_TIMESPEC_HAS_TS_SEC) 2249 static void _MD_set_fileinfo_times(const struct stat* sb, PRFileInfo* info) { 2250 PRInt64 us, s2us; 2251 2252 LL_I2L(s2us, PR_USEC_PER_SEC); 2253 LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec); 2254 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2255 LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000); 2256 LL_ADD(info->modifyTime, info->modifyTime, us); 2257 LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec); 2258 LL_MUL(info->creationTime, info->creationTime, s2us); 2259 LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000); 2260 LL_ADD(info->creationTime, info->creationTime, us); 2261 } 2262 2263 static void _MD_set_fileinfo64_times(const _MDStat64* sb, PRFileInfo64* info) { 2264 PRInt64 us, s2us; 2265 2266 LL_I2L(s2us, PR_USEC_PER_SEC); 2267 LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec); 2268 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2269 LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000); 2270 LL_ADD(info->modifyTime, info->modifyTime, us); 2271 LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec); 2272 LL_MUL(info->creationTime, info->creationTime, s2us); 2273 LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000); 2274 LL_ADD(info->creationTime, info->creationTime, us); 2275 } 2276 # else /* _PR_TIMESPEC_HAS_TS_SEC */ 2277 /* 2278 ** The POSIX timespec structure has tv_sec and tv_nsec. 2279 */ 2280 static void _MD_set_fileinfo_times(const struct stat* sb, PRFileInfo* info) { 2281 PRInt64 us, s2us; 2282 2283 LL_I2L(s2us, PR_USEC_PER_SEC); 2284 LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec); 2285 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2286 LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000); 2287 LL_ADD(info->modifyTime, info->modifyTime, us); 2288 LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec); 2289 LL_MUL(info->creationTime, info->creationTime, s2us); 2290 LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000); 2291 LL_ADD(info->creationTime, info->creationTime, us); 2292 } 2293 2294 static void _MD_set_fileinfo64_times(const _MDStat64* sb, PRFileInfo64* info) { 2295 PRInt64 us, s2us; 2296 2297 LL_I2L(s2us, PR_USEC_PER_SEC); 2298 LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec); 2299 LL_MUL(info->modifyTime, info->modifyTime, s2us); 2300 LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000); 2301 LL_ADD(info->modifyTime, info->modifyTime, us); 2302 LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec); 2303 LL_MUL(info->creationTime, info->creationTime, s2us); 2304 LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000); 2305 LL_ADD(info->creationTime, info->creationTime, us); 2306 } 2307 # endif /* _PR_TIMESPEC_HAS_TS_SEC */ 2308 #elif defined(_PR_STAT_HAS_ONLY_ST_ATIME) 2309 /* 2310 ** struct stat only has st_atime, st_mtime, and st_ctime fields 2311 ** of type time_t. 2312 */ 2313 static void _MD_set_fileinfo_times(const struct stat* sb, PRFileInfo* info) { 2314 PRInt64 s, s2us; 2315 LL_I2L(s2us, PR_USEC_PER_SEC); 2316 LL_I2L(s, sb->st_mtime); 2317 LL_MUL(s, s, s2us); 2318 info->modifyTime = s; 2319 LL_I2L(s, sb->st_ctime); 2320 LL_MUL(s, s, s2us); 2321 info->creationTime = s; 2322 } 2323 2324 static void _MD_set_fileinfo64_times(const _MDStat64* sb, PRFileInfo64* info) { 2325 PRInt64 s, s2us; 2326 LL_I2L(s2us, PR_USEC_PER_SEC); 2327 LL_I2L(s, sb->st_mtime); 2328 LL_MUL(s, s, s2us); 2329 info->modifyTime = s; 2330 LL_I2L(s, sb->st_ctime); 2331 LL_MUL(s, s, s2us); 2332 info->creationTime = s; 2333 } 2334 #else 2335 # error "I don't know yet" 2336 #endif 2337 2338 static int _MD_convert_stat_to_fileinfo(const struct stat* sb, 2339 PRFileInfo* info) { 2340 if (S_IFREG & sb->st_mode) { 2341 info->type = PR_FILE_FILE; 2342 } else if (S_IFDIR & sb->st_mode) { 2343 info->type = PR_FILE_DIRECTORY; 2344 } else { 2345 info->type = PR_FILE_OTHER; 2346 } 2347 2348 #if defined(_PR_HAVE_LARGE_OFF_T) 2349 if (0x7fffffffL < sb->st_size) { 2350 PR_SetError(PR_FILE_TOO_BIG_ERROR, 0); 2351 return -1; 2352 } 2353 #endif /* defined(_PR_HAVE_LARGE_OFF_T) */ 2354 info->size = sb->st_size; 2355 2356 _MD_set_fileinfo_times(sb, info); 2357 return 0; 2358 } /* _MD_convert_stat_to_fileinfo */ 2359 2360 static int _MD_convert_stat64_to_fileinfo64(const _MDStat64* sb, 2361 PRFileInfo64* info) { 2362 if (S_IFREG & sb->st_mode) { 2363 info->type = PR_FILE_FILE; 2364 } else if (S_IFDIR & sb->st_mode) { 2365 info->type = PR_FILE_DIRECTORY; 2366 } else { 2367 info->type = PR_FILE_OTHER; 2368 } 2369 2370 LL_I2L(info->size, sb->st_size); 2371 2372 _MD_set_fileinfo64_times(sb, info); 2373 return 0; 2374 } /* _MD_convert_stat64_to_fileinfo64 */ 2375 2376 PRInt32 _MD_getfileinfo(const char* fn, PRFileInfo* info) { 2377 PRInt32 rv; 2378 struct stat sb; 2379 2380 rv = stat(fn, &sb); 2381 if (rv < 0) { 2382 _PR_MD_MAP_STAT_ERROR(_MD_ERRNO()); 2383 } else if (NULL != info) { 2384 rv = _MD_convert_stat_to_fileinfo(&sb, info); 2385 } 2386 return rv; 2387 } 2388 2389 PRInt32 _MD_getfileinfo64(const char* fn, PRFileInfo64* info) { 2390 _MDStat64 sb; 2391 PRInt32 rv = _md_iovector._stat64(fn, &sb); 2392 if (rv < 0) { 2393 _PR_MD_MAP_STAT_ERROR(_MD_ERRNO()); 2394 } else if (NULL != info) { 2395 rv = _MD_convert_stat64_to_fileinfo64(&sb, info); 2396 } 2397 return rv; 2398 } 2399 2400 PRInt32 _MD_getopenfileinfo(const PRFileDesc* fd, PRFileInfo* info) { 2401 struct stat sb; 2402 PRInt32 rv = fstat(fd->secret->md.osfd, &sb); 2403 if (rv < 0) { 2404 _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO()); 2405 } else if (NULL != info) { 2406 rv = _MD_convert_stat_to_fileinfo(&sb, info); 2407 } 2408 return rv; 2409 } 2410 2411 PRInt32 _MD_getopenfileinfo64(const PRFileDesc* fd, PRFileInfo64* info) { 2412 _MDStat64 sb; 2413 PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb); 2414 if (rv < 0) { 2415 _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO()); 2416 } else if (NULL != info) { 2417 rv = _MD_convert_stat64_to_fileinfo64(&sb, info); 2418 } 2419 return rv; 2420 } 2421 2422 /* 2423 * _md_iovector._open64 must be initialized to 'open' so that _PR_InitLog can 2424 * open the log file during NSPR initialization, before _md_iovector is 2425 * initialized by _PR_MD_FINAL_INIT. This means the log file cannot be a 2426 * large file on some platforms. 2427 */ 2428 struct _MD_IOVector _md_iovector = {open}; 2429 2430 /* 2431 ** These implementations are to emulate large file routines on systems that 2432 ** don't have them. Their goal is to check in case overflow occurs. Otherwise 2433 ** they will just operate as normal using 32-bit file routines. 2434 ** 2435 ** The checking might be pre- or post-op, depending on the semantics. 2436 */ 2437 2438 #if defined(SOLARIS2_5) 2439 2440 static PRIntn _MD_solaris25_fstat64(PRIntn osfd, _MDStat64* buf) { 2441 PRInt32 rv; 2442 struct stat sb; 2443 2444 rv = fstat(osfd, &sb); 2445 if (rv >= 0) { 2446 /* 2447 ** I'm only copying the fields that are immediately needed. 2448 ** If somebody else calls this function, some of the fields 2449 ** may not be defined. 2450 */ 2451 (void)memset(buf, 0, sizeof(_MDStat64)); 2452 buf->st_mode = sb.st_mode; 2453 buf->st_ctim = sb.st_ctim; 2454 buf->st_mtim = sb.st_mtim; 2455 buf->st_size = sb.st_size; 2456 } 2457 return rv; 2458 } /* _MD_solaris25_fstat64 */ 2459 2460 static PRIntn _MD_solaris25_stat64(const char* fn, _MDStat64* buf) { 2461 PRInt32 rv; 2462 struct stat sb; 2463 2464 rv = stat(fn, &sb); 2465 if (rv >= 0) { 2466 /* 2467 ** I'm only copying the fields that are immediately needed. 2468 ** If somebody else calls this function, some of the fields 2469 ** may not be defined. 2470 */ 2471 (void)memset(buf, 0, sizeof(_MDStat64)); 2472 buf->st_mode = sb.st_mode; 2473 buf->st_ctim = sb.st_ctim; 2474 buf->st_mtim = sb.st_mtim; 2475 buf->st_size = sb.st_size; 2476 } 2477 return rv; 2478 } /* _MD_solaris25_stat64 */ 2479 #endif /* defined(SOLARIS2_5) */ 2480 2481 #if defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) 2482 2483 static PROffset64 _MD_Unix_lseek64(PRIntn osfd, PROffset64 offset, 2484 PRIntn whence) { 2485 PRUint64 maxoff; 2486 PROffset64 rv = minus_one; 2487 LL_I2L(maxoff, 0x7fffffff); 2488 if (LL_CMP(offset, <=, maxoff)) { 2489 off_t off; 2490 LL_L2I(off, offset); 2491 LL_I2L(rv, lseek(osfd, off, whence)); 2492 } else { 2493 errno = EFBIG; /* we can't go there */ 2494 } 2495 return rv; 2496 } /* _MD_Unix_lseek64 */ 2497 2498 static void* _MD_Unix_mmap64(void* addr, PRSize len, PRIntn prot, PRIntn flags, 2499 PRIntn fildes, PRInt64 offset) { 2500 PR_SetError(PR_FILE_TOO_BIG_ERROR, 0); 2501 return NULL; 2502 } /* _MD_Unix_mmap64 */ 2503 #endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */ 2504 2505 /* NDK non-unified headers for API < 21 don't have mmap64. However, 2506 * NDK unified headers do provide mmap64 for all API versions when building 2507 * with clang. Therefore, we should provide mmap64 here for API < 21 if we're 2508 * not using clang or if we're using non-unified headers. We check for 2509 * non-unified headers by the lack of __ANDROID_API_L__ macro. */ 2510 #if defined(ANDROID) && __ANDROID_API__ < 21 && \ 2511 (!defined(__clang__) || !defined(__ANDROID_API_L__)) 2512 PR_IMPORT(void) * __mmap2(void*, size_t, int, int, int, size_t); 2513 2514 # define ANDROID_PAGE_SIZE 4096 2515 2516 static void* mmap64(void* addr, size_t len, int prot, int flags, int fd, 2517 loff_t offset) { 2518 if (offset & (ANDROID_PAGE_SIZE - 1)) { 2519 errno = EINVAL; 2520 return MAP_FAILED; 2521 } 2522 return __mmap2(addr, len, prot, flags, fd, offset / ANDROID_PAGE_SIZE); 2523 } 2524 #endif 2525 2526 static void _PR_InitIOV(void) { 2527 #if defined(SOLARIS2_5) 2528 PRLibrary* lib; 2529 void* open64_func; 2530 2531 open64_func = PR_FindSymbolAndLibrary("open64", &lib); 2532 if (NULL != open64_func) { 2533 PR_ASSERT(NULL != lib); 2534 _md_iovector._open64 = (_MD_Open64)open64_func; 2535 _md_iovector._mmap64 = (_MD_Mmap64)PR_FindSymbol(lib, "mmap64"); 2536 _md_iovector._fstat64 = (_MD_Fstat64)PR_FindSymbol(lib, "fstat64"); 2537 _md_iovector._stat64 = (_MD_Stat64)PR_FindSymbol(lib, "stat64"); 2538 _md_iovector._lseek64 = (_MD_Lseek64)PR_FindSymbol(lib, "lseek64"); 2539 (void)PR_UnloadLibrary(lib); 2540 } else { 2541 _md_iovector._open64 = open; 2542 _md_iovector._mmap64 = _MD_Unix_mmap64; 2543 _md_iovector._fstat64 = _MD_solaris25_fstat64; 2544 _md_iovector._stat64 = _MD_solaris25_stat64; 2545 _md_iovector._lseek64 = _MD_Unix_lseek64; 2546 } 2547 #elif defined(_PR_NO_LARGE_FILES) 2548 _md_iovector._open64 = open; 2549 _md_iovector._mmap64 = _MD_Unix_mmap64; 2550 _md_iovector._fstat64 = fstat; 2551 _md_iovector._stat64 = stat; 2552 _md_iovector._lseek64 = _MD_Unix_lseek64; 2553 #elif defined(_PR_HAVE_OFF64_T) 2554 # if (defined(ANDROID) && __ANDROID_API__ < 21) 2555 /* 2556 * Android < 21 doesn't have open64. We pass the O_LARGEFILE flag to open 2557 * in _MD_open. 2558 */ 2559 _md_iovector._open64 = open; 2560 # else 2561 _md_iovector._open64 = open64; 2562 # endif 2563 _md_iovector._mmap64 = mmap64; 2564 # if (defined(ANDROID) && __ANDROID_API__ < 21) 2565 /* Same as the open64 case for Android. */ 2566 _md_iovector._fstat64 = (_MD_Fstat64)fstat; 2567 _md_iovector._stat64 = (_MD_Stat64)stat; 2568 # else 2569 _md_iovector._fstat64 = fstat64; 2570 _md_iovector._stat64 = stat64; 2571 # endif 2572 _md_iovector._lseek64 = lseek64; 2573 #elif defined(_PR_HAVE_LARGE_OFF_T) 2574 _md_iovector._open64 = open; 2575 _md_iovector._mmap64 = mmap; 2576 _md_iovector._fstat64 = fstat; 2577 _md_iovector._stat64 = stat; 2578 _md_iovector._lseek64 = lseek; 2579 #else 2580 # error "I don't know yet" 2581 #endif 2582 LL_I2L(minus_one, -1); 2583 } /* _PR_InitIOV */ 2584 2585 void _PR_UnixInit(void) { 2586 struct sigaction sigact; 2587 int rv; 2588 2589 sigemptyset(&timer_set); 2590 2591 #if !defined(_PR_PTHREADS) 2592 2593 sigaddset(&timer_set, SIGALRM); 2594 sigemptyset(&empty_set); 2595 intr_timeout_ticks = PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS); 2596 2597 # if defined(SOLARIS) 2598 2599 if (getenv("NSPR_SIGSEGV_HANDLE")) { 2600 sigact.sa_handler = sigsegvhandler; 2601 sigact.sa_flags = 0; 2602 sigact.sa_mask = timer_set; 2603 sigaction(SIGSEGV, &sigact, 0); 2604 } 2605 2606 if (getenv("NSPR_SIGABRT_HANDLE")) { 2607 sigact.sa_handler = sigaborthandler; 2608 sigact.sa_flags = 0; 2609 sigact.sa_mask = timer_set; 2610 sigaction(SIGABRT, &sigact, 0); 2611 } 2612 2613 if (getenv("NSPR_SIGBUS_HANDLE")) { 2614 sigact.sa_handler = sigbushandler; 2615 sigact.sa_flags = 0; 2616 sigact.sa_mask = timer_set; 2617 sigaction(SIGBUS, &sigact, 0); 2618 } 2619 2620 # endif 2621 #endif /* !defined(_PR_PTHREADS) */ 2622 2623 sigact.sa_handler = SIG_IGN; 2624 sigemptyset(&sigact.sa_mask); 2625 sigact.sa_flags = 0; 2626 rv = sigaction(SIGPIPE, &sigact, 0); 2627 PR_ASSERT(0 == rv); 2628 2629 _pr_unix_rename_lock = PR_NewLock(); 2630 PR_ASSERT(NULL != _pr_unix_rename_lock); 2631 _pr_Xfe_mon = PR_NewMonitor(); 2632 PR_ASSERT(NULL != _pr_Xfe_mon); 2633 2634 _PR_InitIOV(); /* one last hack */ 2635 } 2636 2637 void _PR_UnixCleanup(void) { 2638 if (_pr_unix_rename_lock) { 2639 PR_DestroyLock(_pr_unix_rename_lock); 2640 _pr_unix_rename_lock = NULL; 2641 } 2642 if (_pr_Xfe_mon) { 2643 PR_DestroyMonitor(_pr_Xfe_mon); 2644 _pr_Xfe_mon = NULL; 2645 } 2646 } 2647 2648 #if !defined(_PR_PTHREADS) 2649 2650 /* 2651 * Variables used by the GC code, initialized in _MD_InitSegs(). 2652 */ 2653 static PRInt32 _pr_zero_fd = -1; 2654 static PRLock* _pr_md_lock = NULL; 2655 2656 /* 2657 * _MD_InitSegs -- 2658 * 2659 * This is Unix's version of _PR_MD_INIT_SEGS(), which is 2660 * called by _PR_InitSegs(), which in turn is called by 2661 * PR_Init(). 2662 */ 2663 void _MD_InitSegs(void) { 2664 # ifdef DEBUG 2665 /* 2666 ** Disable using mmap(2) if NSPR_NO_MMAP is set 2667 */ 2668 if (getenv("NSPR_NO_MMAP")) { 2669 _pr_zero_fd = -2; 2670 return; 2671 } 2672 # endif 2673 _pr_zero_fd = open("/dev/zero", O_RDWR, 0); 2674 /* Prevent the fd from being inherited by child processes */ 2675 fcntl(_pr_zero_fd, F_SETFD, FD_CLOEXEC); 2676 _pr_md_lock = PR_NewLock(); 2677 } 2678 2679 PRStatus _MD_AllocSegment(PRSegment* seg, PRUint32 size, void* vaddr) { 2680 static char* lastaddr = (char*)_PR_STACK_VMBASE; 2681 PRStatus retval = PR_SUCCESS; 2682 int prot; 2683 void* rv; 2684 2685 PR_ASSERT(seg != 0); 2686 PR_ASSERT(size != 0); 2687 2688 PR_Lock(_pr_md_lock); 2689 if (_pr_zero_fd < 0) { 2690 from_heap: 2691 seg->vaddr = PR_MALLOC(size); 2692 if (!seg->vaddr) { 2693 retval = PR_FAILURE; 2694 } else { 2695 seg->size = size; 2696 } 2697 goto exit; 2698 } 2699 2700 prot = PROT_READ | PROT_WRITE; 2701 /* 2702 * On Alpha Linux, the user-level thread stack needs 2703 * to be made executable because longjmp/signal seem 2704 * to put machine instructions on the stack. 2705 */ 2706 # if defined(LINUX) && defined(__alpha) 2707 prot |= PROT_EXEC; 2708 # endif 2709 rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot, _MD_MMAP_FLAGS, 2710 _pr_zero_fd, 0); 2711 if (rv == (void*)-1) { 2712 goto from_heap; 2713 } 2714 lastaddr += size; 2715 seg->vaddr = rv; 2716 seg->size = size; 2717 seg->flags = _PR_SEG_VM; 2718 2719 exit: 2720 PR_Unlock(_pr_md_lock); 2721 return retval; 2722 } 2723 2724 void _MD_FreeSegment(PRSegment* seg) { 2725 if (seg->flags & _PR_SEG_VM) { 2726 (void)munmap(seg->vaddr, seg->size); 2727 } else { 2728 PR_DELETE(seg->vaddr); 2729 } 2730 } 2731 2732 #endif /* _PR_PTHREADS */ 2733 2734 /* 2735 *----------------------------------------------------------------------- 2736 * 2737 * PR_Now -- 2738 * 2739 * Returns the current time in microseconds since the epoch. 2740 * The epoch is midnight January 1, 1970 GMT. 2741 * The implementation is machine dependent. This is the Unix 2742 * implementation. 2743 * Cf. time_t time(time_t *tp) 2744 * 2745 *----------------------------------------------------------------------- 2746 */ 2747 2748 PR_IMPLEMENT(PRTime) 2749 PR_Now(void) { 2750 struct timeval tv; 2751 PRInt64 s, us, s2us; 2752 2753 GETTIMEOFDAY(&tv); 2754 LL_I2L(s2us, PR_USEC_PER_SEC); 2755 LL_I2L(s, tv.tv_sec); 2756 LL_I2L(us, tv.tv_usec); 2757 LL_MUL(s, s, s2us); 2758 LL_ADD(s, s, us); 2759 return s; 2760 } 2761 2762 #if defined(_MD_INTERVAL_USE_GTOD) 2763 /* 2764 * This version of interval times is based on the time of day 2765 * capability offered by the system. This isn't valid for two reasons: 2766 * 1) The time of day is neither linear nor montonically increasing 2767 * 2) The units here are milliseconds. That's not appropriate for our use. 2768 */ 2769 PRIntervalTime _PR_UNIX_GetInterval() { 2770 struct timeval time; 2771 PRIntervalTime ticks; 2772 2773 (void)GETTIMEOFDAY(&time); /* fallicy of course */ 2774 ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */ 2775 ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */ 2776 return ticks; 2777 } /* _PR_UNIX_GetInterval */ 2778 2779 PRIntervalTime _PR_UNIX_TicksPerSecond() { 2780 return 1000; /* this needs some work :) */ 2781 } 2782 #endif 2783 2784 #if defined(_PR_HAVE_CLOCK_MONOTONIC) 2785 PRIntervalTime _PR_UNIX_GetInterval2() { 2786 struct timespec time; 2787 PRIntervalTime ticks; 2788 2789 if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) { 2790 fprintf(stderr, "clock_gettime failed: %d\n", errno); 2791 abort(); 2792 } 2793 2794 ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; 2795 ticks += (PRUint32)time.tv_nsec / PR_NSEC_PER_MSEC; 2796 return ticks; 2797 } 2798 2799 PRIntervalTime _PR_UNIX_TicksPerSecond2() { return 1000; } 2800 #endif 2801 2802 #if !defined(_PR_PTHREADS) 2803 /* 2804 * Wait for I/O on multiple descriptors. 2805 * 2806 * Return 0 if timed out, return -1 if interrupted, 2807 * else return the number of ready descriptors. 2808 */ 2809 PRInt32 _PR_WaitForMultipleFDs(_PRUnixPollDesc* unixpds, PRInt32 pdcnt, 2810 PRIntervalTime timeout) { 2811 PRPollQueue pq; 2812 PRIntn is; 2813 PRInt32 rv; 2814 _PRCPU* io_cpu; 2815 _PRUnixPollDesc *unixpd, *eunixpd; 2816 PRThread* me = _PR_MD_CURRENT_THREAD(); 2817 2818 PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); 2819 2820 if (_PR_PENDING_INTERRUPT(me)) { 2821 me->flags &= ~_PR_INTERRUPT; 2822 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 2823 return -1; 2824 } 2825 2826 pq.pds = unixpds; 2827 pq.npds = pdcnt; 2828 2829 _PR_INTSOFF(is); 2830 _PR_MD_IOQ_LOCK(); 2831 _PR_THREAD_LOCK(me); 2832 2833 pq.thr = me; 2834 io_cpu = me->cpu; 2835 pq.on_ioq = PR_TRUE; 2836 pq.timeout = timeout; 2837 _PR_ADD_TO_IOQ(pq, me->cpu); 2838 2839 # if !defined(_PR_USE_POLL) 2840 eunixpd = unixpds + pdcnt; 2841 for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { 2842 PRInt32 osfd = unixpd->osfd; 2843 if (unixpd->in_flags & _PR_UNIX_POLL_READ) { 2844 FD_SET(osfd, &_PR_FD_READ_SET(me->cpu)); 2845 _PR_FD_READ_CNT(me->cpu)[osfd]++; 2846 } 2847 if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) { 2848 FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu)); 2849 (_PR_FD_WRITE_CNT(me->cpu))[osfd]++; 2850 } 2851 if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) { 2852 FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); 2853 (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++; 2854 } 2855 if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) { 2856 _PR_IOQ_MAX_OSFD(me->cpu) = osfd; 2857 } 2858 } 2859 # endif /* !defined(_PR_USE_POLL) */ 2860 2861 if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) { 2862 _PR_IOQ_TIMEOUT(me->cpu) = timeout; 2863 } 2864 2865 _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt; 2866 2867 _PR_SLEEPQ_LOCK(me->cpu); 2868 _PR_ADD_SLEEPQ(me, timeout); 2869 me->state = _PR_IO_WAIT; 2870 me->io_pending = PR_TRUE; 2871 me->io_suspended = PR_FALSE; 2872 _PR_SLEEPQ_UNLOCK(me->cpu); 2873 _PR_THREAD_UNLOCK(me); 2874 _PR_MD_IOQ_UNLOCK(); 2875 2876 _PR_MD_WAIT(me, timeout); 2877 2878 me->io_pending = PR_FALSE; 2879 me->io_suspended = PR_FALSE; 2880 2881 /* 2882 * This thread should run on the same cpu on which it was blocked; when 2883 * the IO request times out the fd sets and fd counts for the 2884 * cpu are updated below. 2885 */ 2886 PR_ASSERT(me->cpu == io_cpu); 2887 2888 /* 2889 ** If we timed out the pollq might still be on the ioq. Remove it 2890 ** before continuing. 2891 */ 2892 if (pq.on_ioq) { 2893 _PR_MD_IOQ_LOCK(); 2894 /* 2895 * Need to check pq.on_ioq again 2896 */ 2897 if (pq.on_ioq) { 2898 PR_REMOVE_LINK(&pq.links); 2899 # ifndef _PR_USE_POLL 2900 eunixpd = unixpds + pdcnt; 2901 for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { 2902 PRInt32 osfd = unixpd->osfd; 2903 PRInt16 in_flags = unixpd->in_flags; 2904 2905 if (in_flags & _PR_UNIX_POLL_READ) { 2906 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) { 2907 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); 2908 } 2909 } 2910 if (in_flags & _PR_UNIX_POLL_WRITE) { 2911 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) { 2912 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); 2913 } 2914 } 2915 if (in_flags & _PR_UNIX_POLL_EXCEPT) { 2916 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) { 2917 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); 2918 } 2919 } 2920 } 2921 # endif /* _PR_USE_POLL */ 2922 PR_ASSERT(pq.npds == pdcnt); 2923 _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt; 2924 PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0); 2925 } 2926 _PR_MD_IOQ_UNLOCK(); 2927 } 2928 /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */ 2929 if (1 == pdcnt) { 2930 _PR_FAST_INTSON(is); 2931 } else { 2932 _PR_INTSON(is); 2933 } 2934 2935 if (_PR_PENDING_INTERRUPT(me)) { 2936 me->flags &= ~_PR_INTERRUPT; 2937 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 2938 return -1; 2939 } 2940 2941 rv = 0; 2942 if (pq.on_ioq == PR_FALSE) { 2943 /* Count the number of ready descriptors */ 2944 while (--pdcnt >= 0) { 2945 if (unixpds->out_flags != 0) { 2946 rv++; 2947 } 2948 unixpds++; 2949 } 2950 } 2951 2952 return rv; 2953 } 2954 2955 /* 2956 * Unblock threads waiting for I/O 2957 * used when interrupting threads 2958 * 2959 * NOTE: The thread lock should held when this function is called. 2960 * On return, the thread lock is released. 2961 */ 2962 void _PR_Unblock_IO_Wait(PRThread* thr) { 2963 int pri = thr->priority; 2964 _PRCPU* cpu = thr->cpu; 2965 2966 /* 2967 * GLOBAL threads wakeup periodically to check for interrupt 2968 */ 2969 if (_PR_IS_NATIVE_THREAD(thr)) { 2970 _PR_THREAD_UNLOCK(thr); 2971 return; 2972 } 2973 2974 PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ)); 2975 _PR_SLEEPQ_LOCK(cpu); 2976 _PR_DEL_SLEEPQ(thr, PR_TRUE); 2977 _PR_SLEEPQ_UNLOCK(cpu); 2978 2979 PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD)); 2980 thr->state = _PR_RUNNABLE; 2981 _PR_RUNQ_LOCK(cpu); 2982 _PR_ADD_RUNQ(thr, cpu, pri); 2983 _PR_RUNQ_UNLOCK(cpu); 2984 _PR_THREAD_UNLOCK(thr); 2985 _PR_MD_WAKEUP_WAITER(thr); 2986 } 2987 #endif /* !defined(_PR_PTHREADS) */ 2988 2989 /* 2990 * When a nonblocking connect has completed, determine whether it 2991 * succeeded or failed, and if it failed, what the error code is. 2992 * 2993 * The function returns the error code. An error code of 0 means 2994 * that the nonblocking connect succeeded. 2995 */ 2996 2997 int _MD_unix_get_nonblocking_connect_error(int osfd) { 2998 #if defined(NTO) 2999 /* Neutrino does not support the SO_ERROR socket option */ 3000 PRInt32 rv; 3001 PRNetAddr addr; 3002 _PRSockLen_t addrlen = sizeof(addr); 3003 3004 /* Test to see if we are using the Tiny TCP/IP Stack or the Full one. */ 3005 struct statvfs superblock; 3006 rv = fstatvfs(osfd, &superblock); 3007 if (rv == 0) { 3008 if (strcmp(superblock.f_basetype, "ttcpip") == 0) { 3009 /* Using the Tiny Stack! */ 3010 rv = getpeername(osfd, (struct sockaddr*)&addr, (_PRSockLen_t*)&addrlen); 3011 if (rv == -1) { 3012 int errno_copy = errno; /* make a copy so I don't 3013 * accidentally reset */ 3014 3015 if (errno_copy == ENOTCONN) { 3016 struct stat StatInfo; 3017 rv = fstat(osfd, &StatInfo); 3018 if (rv == 0) { 3019 time_t current_time = time(NULL); 3020 3021 /* 3022 * this is a real hack, can't explain why it 3023 * works it just does 3024 */ 3025 if (abs(current_time - StatInfo.st_atime) < 5) { 3026 return ECONNREFUSED; 3027 } else { 3028 return ETIMEDOUT; 3029 } 3030 } else { 3031 return ECONNREFUSED; 3032 } 3033 } else { 3034 return errno_copy; 3035 } 3036 } else { 3037 /* No Error */ 3038 return 0; 3039 } 3040 } else { 3041 /* Have the FULL Stack which supports SO_ERROR */ 3042 /* Hasn't been written yet, never been tested! */ 3043 /* Jerry.Kirk@Nexwarecorp.com */ 3044 3045 int err; 3046 _PRSockLen_t optlen = sizeof(err); 3047 3048 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen) == -1) { 3049 return errno; 3050 } else { 3051 return err; 3052 } 3053 } 3054 } else { 3055 return ECONNREFUSED; 3056 } 3057 #else 3058 int err; 3059 _PRSockLen_t optlen = sizeof(err); 3060 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen) == -1) { 3061 return errno; 3062 } 3063 return err; 3064 3065 #endif 3066 } 3067 3068 /************************************************************************/ 3069 3070 /* 3071 ** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread 3072 ** safe. Unfortunately, neither is mozilla. To make these programs work 3073 ** in a pre-emptive threaded environment, we need to use a lock. 3074 */ 3075 3076 void _PR_XLock(void) { PR_EnterMonitor(_pr_Xfe_mon); } 3077 3078 void _PR_XUnlock(void) { PR_ExitMonitor(_pr_Xfe_mon); } 3079 3080 PRBool _PR_XIsLocked(void) { 3081 return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE; 3082 } 3083 3084 #if defined(HAVE_FCNTL_FILE_LOCKING) 3085 3086 PRStatus _MD_LockFile(PRInt32 f) { 3087 PRInt32 rv; 3088 struct flock arg; 3089 3090 arg.l_type = F_WRLCK; 3091 arg.l_whence = SEEK_SET; 3092 arg.l_start = 0; 3093 arg.l_len = 0; /* until EOF */ 3094 rv = fcntl(f, F_SETLKW, &arg); 3095 if (rv == 0) { 3096 return PR_SUCCESS; 3097 } 3098 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3099 return PR_FAILURE; 3100 } 3101 3102 PRStatus _MD_TLockFile(PRInt32 f) { 3103 PRInt32 rv; 3104 struct flock arg; 3105 3106 arg.l_type = F_WRLCK; 3107 arg.l_whence = SEEK_SET; 3108 arg.l_start = 0; 3109 arg.l_len = 0; /* until EOF */ 3110 rv = fcntl(f, F_SETLK, &arg); 3111 if (rv == 0) { 3112 return PR_SUCCESS; 3113 } 3114 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3115 return PR_FAILURE; 3116 } 3117 3118 PRStatus _MD_UnlockFile(PRInt32 f) { 3119 PRInt32 rv; 3120 struct flock arg; 3121 3122 arg.l_type = F_UNLCK; 3123 arg.l_whence = SEEK_SET; 3124 arg.l_start = 0; 3125 arg.l_len = 0; /* until EOF */ 3126 rv = fcntl(f, F_SETLK, &arg); 3127 if (rv == 0) { 3128 return PR_SUCCESS; 3129 } 3130 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3131 return PR_FAILURE; 3132 } 3133 3134 #elif defined(HAVE_BSD_FLOCK) 3135 3136 # include <sys/file.h> 3137 3138 PRStatus _MD_LockFile(PRInt32 f) { 3139 PRInt32 rv; 3140 rv = flock(f, LOCK_EX); 3141 if (rv == 0) { 3142 return PR_SUCCESS; 3143 } 3144 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3145 return PR_FAILURE; 3146 } 3147 3148 PRStatus _MD_TLockFile(PRInt32 f) { 3149 PRInt32 rv; 3150 rv = flock(f, LOCK_EX | LOCK_NB); 3151 if (rv == 0) { 3152 return PR_SUCCESS; 3153 } 3154 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3155 return PR_FAILURE; 3156 } 3157 3158 PRStatus _MD_UnlockFile(PRInt32 f) { 3159 PRInt32 rv; 3160 rv = flock(f, LOCK_UN); 3161 if (rv == 0) { 3162 return PR_SUCCESS; 3163 } 3164 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); 3165 return PR_FAILURE; 3166 } 3167 #else 3168 3169 PRStatus _MD_LockFile(PRInt32 f) { 3170 PRInt32 rv; 3171 rv = lockf(f, F_LOCK, 0); 3172 if (rv == 0) { 3173 return PR_SUCCESS; 3174 } 3175 _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); 3176 return PR_FAILURE; 3177 } 3178 3179 PRStatus _MD_TLockFile(PRInt32 f) { 3180 PRInt32 rv; 3181 rv = lockf(f, F_TLOCK, 0); 3182 if (rv == 0) { 3183 return PR_SUCCESS; 3184 } 3185 _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); 3186 return PR_FAILURE; 3187 } 3188 3189 PRStatus _MD_UnlockFile(PRInt32 f) { 3190 PRInt32 rv; 3191 rv = lockf(f, F_ULOCK, 0); 3192 if (rv == 0) { 3193 return PR_SUCCESS; 3194 } 3195 _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); 3196 return PR_FAILURE; 3197 } 3198 #endif 3199 3200 PRStatus _MD_gethostname(char* name, PRUint32 namelen) { 3201 PRIntn rv; 3202 3203 rv = gethostname(name, namelen); 3204 if (0 == rv) { 3205 return PR_SUCCESS; 3206 } 3207 _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO()); 3208 return PR_FAILURE; 3209 } 3210 3211 PRStatus _MD_getsysinfo(PRSysInfo cmd, char* name, PRUint32 namelen) { 3212 struct utsname info; 3213 3214 PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE) || 3215 (cmd == PR_SI_RELEASE_BUILD)); 3216 3217 if (uname(&info) == -1) { 3218 _PR_MD_MAP_DEFAULT_ERROR(errno); 3219 return PR_FAILURE; 3220 } 3221 if (PR_SI_SYSNAME == cmd) { 3222 (void)PR_snprintf(name, namelen, info.sysname); 3223 } else if (PR_SI_RELEASE == cmd) { 3224 (void)PR_snprintf(name, namelen, info.release); 3225 } else if (PR_SI_RELEASE_BUILD == cmd) { 3226 (void)PR_snprintf(name, namelen, info.version); 3227 } else { 3228 return PR_FAILURE; 3229 } 3230 return PR_SUCCESS; 3231 } 3232 3233 /* 3234 ******************************************************************* 3235 * 3236 * Memory-mapped files 3237 * 3238 ******************************************************************* 3239 */ 3240 3241 PRStatus _MD_CreateFileMap(PRFileMap* fmap, PRInt64 size) { 3242 PRFileInfo info; 3243 PRUint32 sz; 3244 3245 LL_L2UI(sz, size); 3246 if (sz) { 3247 if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) { 3248 return PR_FAILURE; 3249 } 3250 if (sz > info.size) { 3251 /* 3252 * Need to extend the file 3253 */ 3254 if (fmap->prot != PR_PROT_READWRITE) { 3255 PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0); 3256 return PR_FAILURE; 3257 } 3258 if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) { 3259 return PR_FAILURE; 3260 } 3261 if (PR_Write(fmap->fd, "", 1) != 1) { 3262 return PR_FAILURE; 3263 } 3264 } 3265 } 3266 if (fmap->prot == PR_PROT_READONLY) { 3267 fmap->md.prot = PROT_READ; 3268 #if defined(DARWIN) || defined(ANDROID) 3269 /* 3270 * This is needed on OS X because its implementation of 3271 * POSIX shared memory returns an error for MAP_PRIVATE, even 3272 * when the mapping is read-only. 3273 * 3274 * And this is needed on Android, because mapping ashmem with 3275 * MAP_PRIVATE creates a mapping of zeroed memory instead of 3276 * the shm contents. 3277 */ 3278 fmap->md.flags = MAP_SHARED; 3279 #else 3280 fmap->md.flags = MAP_PRIVATE; 3281 #endif 3282 } else if (fmap->prot == PR_PROT_READWRITE) { 3283 fmap->md.prot = PROT_READ | PROT_WRITE; 3284 fmap->md.flags = MAP_SHARED; 3285 } else { 3286 PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY); 3287 fmap->md.prot = PROT_READ | PROT_WRITE; 3288 fmap->md.flags = MAP_PRIVATE; 3289 } 3290 return PR_SUCCESS; 3291 } 3292 3293 void* _MD_MemMap(PRFileMap* fmap, PRInt64 offset, PRUint32 len) { 3294 PRInt32 off; 3295 void* addr; 3296 3297 LL_L2I(off, offset); 3298 if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags, 3299 fmap->fd->secret->md.osfd, off)) == (void*)-1) { 3300 _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO()); 3301 addr = NULL; 3302 } 3303 return addr; 3304 } 3305 3306 PRStatus _MD_MemUnmap(void* addr, PRUint32 len) { 3307 if (munmap(addr, len) == 0) { 3308 return PR_SUCCESS; 3309 } 3310 _PR_MD_MAP_DEFAULT_ERROR(errno); 3311 return PR_FAILURE; 3312 } 3313 3314 PRStatus _MD_CloseFileMap(PRFileMap* fmap) { 3315 if (PR_TRUE == fmap->md.isAnonFM) { 3316 PRStatus rc = PR_Close(fmap->fd); 3317 if (PR_FAILURE == rc) { 3318 PR_LOG(_pr_io_lm, PR_LOG_DEBUG, 3319 ("_MD_CloseFileMap(): error closing anonymnous file map osfd")); 3320 return PR_FAILURE; 3321 } 3322 } 3323 PR_DELETE(fmap); 3324 return PR_SUCCESS; 3325 } 3326 3327 PRStatus _MD_SyncMemMap(PRFileDesc* fd, void* addr, PRUint32 len) { 3328 /* msync(..., MS_SYNC) alone is sufficient to flush modified data to disk 3329 * synchronously. It is not necessary to call fsync. */ 3330 if (msync(addr, len, MS_SYNC) == 0) { 3331 return PR_SUCCESS; 3332 } 3333 _PR_MD_MAP_DEFAULT_ERROR(errno); 3334 return PR_FAILURE; 3335 } 3336 3337 #if defined(_PR_NEED_FAKE_POLL) 3338 3339 /* 3340 * Some platforms don't have poll(). For easier porting of code 3341 * that calls poll(), we emulate poll() using select(). 3342 */ 3343 3344 int poll(struct pollfd* filedes, unsigned long nfds, int timeout) { 3345 int i; 3346 int rv; 3347 int maxfd; 3348 fd_set rd, wr, ex; 3349 struct timeval tv, *tvp; 3350 3351 if (timeout < 0 && timeout != -1) { 3352 errno = EINVAL; 3353 return -1; 3354 } 3355 3356 if (timeout == -1) { 3357 tvp = NULL; 3358 } else { 3359 tv.tv_sec = timeout / 1000; 3360 tv.tv_usec = (timeout % 1000) * 1000; 3361 tvp = &tv; 3362 } 3363 3364 maxfd = -1; 3365 FD_ZERO(&rd); 3366 FD_ZERO(&wr); 3367 FD_ZERO(&ex); 3368 3369 for (i = 0; i < nfds; i++) { 3370 int osfd = filedes[i].fd; 3371 int events = filedes[i].events; 3372 PRBool fdHasEvent = PR_FALSE; 3373 3374 PR_ASSERT(osfd < FD_SETSIZE); 3375 if (osfd < 0 || osfd >= FD_SETSIZE) { 3376 continue; /* Skip this osfd. */ 3377 } 3378 3379 /* 3380 * Map the poll events to the select fd_sets. 3381 * POLLIN, POLLRDNORM ===> readable 3382 * POLLOUT, POLLWRNORM ===> writable 3383 * POLLPRI, POLLRDBAND ===> exception 3384 * POLLNORM, POLLWRBAND (and POLLMSG on some platforms) 3385 * are ignored. 3386 * 3387 * The output events POLLERR and POLLHUP are never turned on. 3388 * POLLNVAL may be turned on. 3389 */ 3390 3391 if (events & (POLLIN | POLLRDNORM)) { 3392 FD_SET(osfd, &rd); 3393 fdHasEvent = PR_TRUE; 3394 } 3395 if (events & (POLLOUT | POLLWRNORM)) { 3396 FD_SET(osfd, &wr); 3397 fdHasEvent = PR_TRUE; 3398 } 3399 if (events & (POLLPRI | POLLRDBAND)) { 3400 FD_SET(osfd, &ex); 3401 fdHasEvent = PR_TRUE; 3402 } 3403 if (fdHasEvent && osfd > maxfd) { 3404 maxfd = osfd; 3405 } 3406 } 3407 3408 rv = select(maxfd + 1, &rd, &wr, &ex, tvp); 3409 3410 /* Compute poll results */ 3411 if (rv > 0) { 3412 rv = 0; 3413 for (i = 0; i < nfds; i++) { 3414 PRBool fdHasEvent = PR_FALSE; 3415 3416 filedes[i].revents = 0; 3417 if (filedes[i].fd < 0) { 3418 continue; 3419 } 3420 if (filedes[i].fd >= FD_SETSIZE) { 3421 filedes[i].revents |= POLLNVAL; 3422 continue; 3423 } 3424 if (FD_ISSET(filedes[i].fd, &rd)) { 3425 if (filedes[i].events & POLLIN) { 3426 filedes[i].revents |= POLLIN; 3427 } 3428 if (filedes[i].events & POLLRDNORM) { 3429 filedes[i].revents |= POLLRDNORM; 3430 } 3431 fdHasEvent = PR_TRUE; 3432 } 3433 if (FD_ISSET(filedes[i].fd, &wr)) { 3434 if (filedes[i].events & POLLOUT) { 3435 filedes[i].revents |= POLLOUT; 3436 } 3437 if (filedes[i].events & POLLWRNORM) { 3438 filedes[i].revents |= POLLWRNORM; 3439 } 3440 fdHasEvent = PR_TRUE; 3441 } 3442 if (FD_ISSET(filedes[i].fd, &ex)) { 3443 if (filedes[i].events & POLLPRI) { 3444 filedes[i].revents |= POLLPRI; 3445 } 3446 if (filedes[i].events & POLLRDBAND) { 3447 filedes[i].revents |= POLLRDBAND; 3448 } 3449 fdHasEvent = PR_TRUE; 3450 } 3451 if (fdHasEvent) { 3452 rv++; 3453 } 3454 } 3455 PR_ASSERT(rv > 0); 3456 } else if (rv == -1 && errno == EBADF) { 3457 rv = 0; 3458 for (i = 0; i < nfds; i++) { 3459 filedes[i].revents = 0; 3460 if (filedes[i].fd < 0) { 3461 continue; 3462 } 3463 if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) { 3464 filedes[i].revents = POLLNVAL; 3465 rv++; 3466 } 3467 } 3468 PR_ASSERT(rv > 0); 3469 } 3470 PR_ASSERT(-1 != timeout || rv != 0); 3471 3472 return rv; 3473 } 3474 #endif /* _PR_NEED_FAKE_POLL */