Changeset 101805 in vbox for trunk/src/libs/xpcom18a4
- Timestamp:
- Nov 5, 2023 9:36:46 AM (17 months ago)
- svn:sync-xref-src-repo-rev:
- 159901
- Location:
- trunk/src/libs/xpcom18a4
- Files:
-
- 2 deleted
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/Makefile.kmk
r101804 r101805 523 523 nsprpub/pr/src/linking/prlink.c \ 524 524 nsprpub/pr/src/md/prosdep.c \ 525 nsprpub/pr/src/memory/prseg.c \526 525 nsprpub/pr/src/memory/prshm.c \ 527 526 nsprpub/pr/src/memory/prshma.c \ -
trunk/src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h
r101777 r101805 47 47 */ 48 48 49 #if defined(_PR_PTHREADS)50 49 #include <pthread.h> 51 #endif52 53 #if defined(_PR_BTHREADS)54 #include <kernel/OS.h>55 #endif56 57 #ifdef WINNT58 /* Need to force service-pack 3 extensions to be defined by59 ** setting _WIN32_WINNT to NT 4.0 for winsock.h, winbase.h, winnt.h.60 */61 #ifndef _WIN32_WINNT62 #define _WIN32_WINNT 0x040063 #elif (_WIN32_WINNT < 0x0400)64 #undef _WIN32_WINNT65 #define _WIN32_WINNT 0x040066 #endif /* _WIN32_WINNT */67 #endif /* WINNT */68 50 69 51 #include "nspr.h" … … 159 141 typedef struct _MDFileMap _MDFileMap; 160 142 161 #if defined(_PR_PTHREADS)162 163 143 /* 164 144 ** The following definitions are unique to implementing NSPR using pthreads. … … 225 205 226 206 NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); 227 228 #else /* defined(_PR_PTHREADS) */229 230 NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);231 232 /*233 ** This section is contains those parts needed to implement NSPR on234 ** platforms in general. One would assume that the pthreads implementation235 ** included lots of the same types, at least conceptually.236 */237 238 /*239 * Local threads only. No multiple CPU support and hence all the240 * following routines are no-op.241 */242 #ifdef _PR_LOCAL_THREADS_ONLY243 244 #define _PR_MD_SUSPEND_THREAD(thread)245 #define _PR_MD_RESUME_THREAD(thread)246 #define _PR_MD_SUSPEND_CPU(cpu)247 #define _PR_MD_RESUME_CPU(cpu)248 #define _PR_MD_BEGIN_SUSPEND_ALL()249 #define _PR_MD_END_SUSPEND_ALL()250 #define _PR_MD_BEGIN_RESUME_ALL()251 #define _PR_MD_END_RESUME_ALL()252 #define _PR_MD_INIT_ATTACHED_THREAD(thread) PR_FAILURE253 254 #endif255 256 typedef struct _PRCPUQueue _PRCPUQueue;257 typedef struct _PRCPU _PRCPU;258 typedef struct _MDCPU _MDCPU;259 260 struct _PRCPUQueue {261 _MDLock runQLock; /* lock for the run + wait queues */262 _MDLock sleepQLock; /* lock for the run + wait queues */263 _MDLock miscQLock; /* lock for the run + wait queues */264 265 PRCList runQ[PR_PRIORITY_LAST + 1]; /* run queue for this CPU */266 PRUint32 runQReadyMask;267 PRCList sleepQ;268 PRIntervalTime sleepQmax;269 PRCList pauseQ;270 PRCList suspendQ;271 PRCList waitingToJoinQ;272 273 PRUintn numCPUs; /* number of CPUs using this Q */274 };275 276 struct _PRCPU {277 PRCList links; /* link list of CPUs */278 PRUint32 id; /* id for this CPU */279 280 union {281 PRInt32 bits;282 PRUint8 missed[4];283 } u;284 PRIntn where; /* index into u.missed */285 PRPackedBool paused; /* cpu is paused */286 PRPackedBool exit; /* cpu should exit */287 288 PRThread *thread; /* native thread for this CPUThread */289 PRThread *idle_thread; /* user-level idle thread for this CPUThread */290 291 PRIntervalTime last_clock; /* the last time we went into292 * _PR_ClockInterrupt() on this CPU293 */294 295 _PRCPUQueue *queue;296 297 _MDCPU md;298 };299 300 typedef struct _PRInterruptTable {301 const char *name;302 PRUintn missed_bit;303 void (*handler)(void);304 } _PRInterruptTable;305 306 #define _PR_CPU_PTR(_qp) \307 ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links)))308 309 #if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \310 && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))311 #define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD())312 #endif313 314 #ifdef _PR_LOCAL_THREADS_ONLY315 316 NSPR_API(struct _PRCPU *) _pr_currentCPU;317 NSPR_API(PRThread *) _pr_currentThread;318 NSPR_API(PRThread *) _pr_lastThread;319 NSPR_API(PRInt32) _pr_intsOff;320 321 #define _MD_CURRENT_CPU() (_pr_currentCPU)322 #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (_cpu))323 #define _MD_CURRENT_THREAD() (_pr_currentThread)324 #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))325 #define _MD_LAST_THREAD() (_pr_lastThread)326 #define _MD_SET_LAST_THREAD(t) (_pr_lastThread = t)327 328 #ifndef XP_MAC329 #define _MD_GET_INTSOFF() (_pr_intsOff)330 #define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val)331 #endif332 333 334 /* The unbalanced curly braces in these two macros are intentional */335 #define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is);336 #define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); }337 338 #endif /* _PR_LOCAL_THREADS_ONLY */339 340 extern PRInt32 _native_threads_only;341 342 #if defined(_PR_GLOBAL_THREADS_ONLY)343 344 #define _MD_GET_INTSOFF() 0345 #define _MD_SET_INTSOFF(_val)346 #define _PR_INTSOFF(_is)347 #define _PR_FAST_INTSON(_is)348 #define _PR_INTSON(_is)349 #define _PR_THREAD_LOCK(_thread)350 #define _PR_THREAD_UNLOCK(_thread)351 #define _PR_RUNQ_LOCK(cpu)352 #define _PR_RUNQ_UNLOCK(cpu)353 #define _PR_SLEEPQ_LOCK(thread)354 #define _PR_SLEEPQ_UNLOCK(thread)355 #define _PR_MISCQ_LOCK(thread)356 #define _PR_MISCQ_UNLOCK(thread)357 #define _PR_CPU_LIST_LOCK()358 #define _PR_CPU_LIST_UNLOCK()359 360 #define _PR_ADD_RUNQ(_thread, _cpu, _pri)361 #define _PR_DEL_RUNQ(_thread)362 #define _PR_ADD_SLEEPQ(_thread, _timeout)363 #define _PR_DEL_SLEEPQ(_thread, _propogate)364 #define _PR_ADD_JOINQ(_thread, _cpu)365 #define _PR_DEL_JOINQ(_thread)366 #define _PR_ADD_SUSPENDQ(_thread, _cpu)367 #define _PR_DEL_SUSPENDQ(_thread)368 369 #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU)370 371 #define _PR_IS_NATIVE_THREAD(thread) 1372 #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1373 374 #else375 376 #ifdef XP_MAC377 378 #define _PR_INTSOFF(_is) _MD_INTSOFF(_is)379 380 #else /* XP_MAC */381 382 #define _PR_INTSOFF(_is) \383 PR_BEGIN_MACRO \384 (_is) = _PR_MD_GET_INTSOFF(); \385 _PR_MD_SET_INTSOFF(1); \386 PR_END_MACRO387 388 #endif /* XP_MAC */389 390 #define _PR_FAST_INTSON(_is) \391 PR_BEGIN_MACRO \392 _PR_MD_SET_INTSOFF(_is); \393 PR_END_MACRO394 395 #define _PR_INTSON(_is) \396 PR_BEGIN_MACRO \397 if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \398 _PR_IntsOn((_PR_MD_CURRENT_CPU())); \399 _PR_MD_SET_INTSOFF(_is); \400 PR_END_MACRO401 402 #ifdef _PR_LOCAL_THREADS_ONLY403 404 #define _PR_IS_NATIVE_THREAD(thread) 0405 #define _PR_THREAD_LOCK(_thread)406 #define _PR_THREAD_UNLOCK(_thread)407 #define _PR_RUNQ_LOCK(cpu)408 #define _PR_RUNQ_UNLOCK(cpu)409 #define _PR_SLEEPQ_LOCK(thread)410 #define _PR_SLEEPQ_UNLOCK(thread)411 #define _PR_MISCQ_LOCK(thread)412 #define _PR_MISCQ_UNLOCK(thread)413 #define _PR_CPU_LIST_LOCK()414 #define _PR_CPU_LIST_UNLOCK()415 416 #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \417 PR_BEGIN_MACRO \418 PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \419 _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \420 PR_END_MACRO421 422 #define _PR_DEL_RUNQ(_thread) \423 PR_BEGIN_MACRO \424 _PRCPU *_cpu = _thread->cpu; \425 PRInt32 _pri = _thread->priority; \426 PR_REMOVE_LINK(&(_thread)->links); \427 if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \428 _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \429 PR_END_MACRO430 431 #define _PR_ADD_SLEEPQ(_thread, _timeout) \432 _PR_AddSleepQ(_thread, _timeout);433 434 #define _PR_DEL_SLEEPQ(_thread, _propogate) \435 _PR_DelSleepQ(_thread, _propogate);436 437 #define _PR_ADD_JOINQ(_thread, _cpu) \438 PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu));439 440 #define _PR_DEL_JOINQ(_thread) \441 PR_REMOVE_LINK(&(_thread)->links);442 443 #define _PR_ADD_SUSPENDQ(_thread, _cpu) \444 PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu));445 446 #define _PR_DEL_SUSPENDQ(_thread) \447 PR_REMOVE_LINK(&(_thread)->links);448 449 #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU)450 451 #define _PR_IS_NATIVE_THREAD_SUPPORTED() 0452 453 #else /* _PR_LOCAL_THREADS_ONLY */454 455 /* These are for the "combined" thread model */456 457 #define _PR_THREAD_LOCK(_thread) \458 _PR_MD_LOCK(&(_thread)->threadLock);459 460 #define _PR_THREAD_UNLOCK(_thread) \461 _PR_MD_UNLOCK(&(_thread)->threadLock);462 463 #define _PR_RUNQ_LOCK(_cpu) \464 PR_BEGIN_MACRO \465 _PR_MD_LOCK(&(_cpu)->queue->runQLock );\466 PR_END_MACRO467 468 #define _PR_RUNQ_UNLOCK(_cpu) \469 PR_BEGIN_MACRO \470 _PR_MD_UNLOCK(&(_cpu)->queue->runQLock );\471 PR_END_MACRO472 473 #define _PR_SLEEPQ_LOCK(_cpu) \474 _PR_MD_LOCK(&(_cpu)->queue->sleepQLock );475 476 #define _PR_SLEEPQ_UNLOCK(_cpu) \477 _PR_MD_UNLOCK(&(_cpu)->queue->sleepQLock );478 479 #define _PR_MISCQ_LOCK(_cpu) \480 _PR_MD_LOCK(&(_cpu)->queue->miscQLock );481 482 #define _PR_MISCQ_UNLOCK(_cpu) \483 _PR_MD_UNLOCK(&(_cpu)->queue->miscQLock );484 485 #define _PR_CPU_LIST_LOCK() _PR_MD_LOCK(&_pr_cpuLock)486 #define _PR_CPU_LIST_UNLOCK() _PR_MD_UNLOCK(&_pr_cpuLock)487 488 #define QUEUE_RUN 0x1489 #define QUEUE_SLEEP 0x2490 #define QUEUE_JOIN 0x4491 #define QUEUE_SUSPEND 0x8492 #define QUEUE_LOCK 0x10493 494 #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \495 PR_BEGIN_MACRO \496 PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \497 _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \498 PR_ASSERT((_thread)->queueCount == 0); \499 (_thread)->queueCount = QUEUE_RUN; \500 PR_END_MACRO501 502 #define _PR_DEL_RUNQ(_thread) \503 PR_BEGIN_MACRO \504 _PRCPU *_cpu = _thread->cpu; \505 PRInt32 _pri = _thread->priority; \506 PR_REMOVE_LINK(&(_thread)->links); \507 if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \508 _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \509 PR_ASSERT((_thread)->queueCount == QUEUE_RUN);\510 (_thread)->queueCount = 0; \511 PR_END_MACRO512 513 #define _PR_ADD_SLEEPQ(_thread, _timeout) \514 PR_ASSERT((_thread)->queueCount == 0); \515 (_thread)->queueCount = QUEUE_SLEEP; \516 _PR_AddSleepQ(_thread, _timeout);517 518 #define _PR_DEL_SLEEPQ(_thread, _propogate) \519 PR_ASSERT((_thread)->queueCount == QUEUE_SLEEP);\520 (_thread)->queueCount = 0; \521 _PR_DelSleepQ(_thread, _propogate);522 523 #define _PR_ADD_JOINQ(_thread, _cpu) \524 PR_ASSERT((_thread)->queueCount == 0); \525 (_thread)->queueCount = QUEUE_JOIN; \526 PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu));527 528 #define _PR_DEL_JOINQ(_thread) \529 PR_ASSERT((_thread)->queueCount == QUEUE_JOIN);\530 (_thread)->queueCount = 0; \531 PR_REMOVE_LINK(&(_thread)->links);532 533 #define _PR_ADD_SUSPENDQ(_thread, _cpu) \534 PR_ASSERT((_thread)->queueCount == 0); \535 (_thread)->queueCount = QUEUE_SUSPEND; \536 PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu));537 538 #define _PR_DEL_SUSPENDQ(_thread) \539 PR_ASSERT((_thread)->queueCount == QUEUE_SUSPEND);\540 (_thread)->queueCount = 0; \541 PR_REMOVE_LINK(&(_thread)->links);542 543 #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) \544 (_thread)->cpu = (_newCPU);545 546 #define _PR_IS_NATIVE_THREAD(thread) (thread->flags & _PR_GLOBAL_SCOPE)547 #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1548 549 #endif /* _PR_LOCAL_THREADS_ONLY */550 551 #endif /* _PR_GLOBAL_THREADS_ONLY */552 553 #define _PR_SET_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 1554 #define _PR_CLEAR_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 0555 556 extern _PRInterruptTable _pr_interruptTable[];557 558 /* Bits for _pr_interruptState.u.missed[0,1] */559 #define _PR_MISSED_CLOCK 0x1560 #define _PR_MISSED_IO 0x2561 #define _PR_MISSED_CHILD 0x4562 563 extern void _PR_IntsOn(_PRCPU *cpu);564 565 NSPR_API(void) _PR_WakeupCPU(void);566 NSPR_API(void) _PR_PauseCPU(void);567 568 /************************************************************************/569 570 #define _PR_LOCK_LOCK(_lock) \571 _PR_MD_LOCK(&(_lock)->ilock);572 #define _PR_LOCK_UNLOCK(_lock) \573 _PR_MD_UNLOCK(&(_lock)->ilock);574 575 extern void _PR_UnblockLockWaiter(PRLock *lock);576 577 #define _PR_LOCK_PTR(_qp) \578 ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links)))579 580 /************************************************************************/581 582 #define _PR_CVAR_LOCK(_cvar) \583 _PR_MD_LOCK(&(_cvar)->ilock);584 #define _PR_CVAR_UNLOCK(_cvar) \585 _PR_MD_UNLOCK(&(_cvar)->ilock);586 587 extern PRStatus _PR_WaitCondVar(588 PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout);589 extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen);590 591 NSPR_API(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky);592 593 /* PRThread.flags */594 #define _PR_SYSTEM 0x01595 #define _PR_INTERRUPT 0x02596 #define _PR_ATTACHED 0x04 /* created via PR_AttachThread */597 #define _PR_PRIMORDIAL 0x08 /* the thread that called PR_Init */598 #define _PR_ON_SLEEPQ 0x10 /* thread is on the sleepQ */599 #define _PR_ON_PAUSEQ 0x20 /* thread is on the pauseQ */600 #define _PR_SUSPENDING 0x40 /* thread wants to suspend */601 #define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */602 #define _PR_IDLE_THREAD 0x200 /* this is an idle thread */603 #define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */604 #define _PR_BOUND_THREAD 0x800 /* a bound thread */605 #define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */606 607 /* PRThread.state */608 #define _PR_UNBORN 0609 #define _PR_RUNNABLE 1610 #define _PR_RUNNING 2611 #define _PR_LOCK_WAIT 3612 #define _PR_COND_WAIT 4613 #define _PR_JOIN_WAIT 5614 #define _PR_IO_WAIT 6615 #define _PR_SUSPENDED 7616 #define _PR_DEAD_STATE 8 /* for debugging */617 618 /* PRThreadStack.flags */619 #define _PR_STACK_VM 0x1 /* using vm instead of malloc */620 #define _PR_STACK_MAPPED 0x2 /* vm is mapped */621 #define _PR_STACK_PRIMORDIAL 0x4 /* stack for primordial thread */622 623 /*624 ** If the default stcksize from the client is zero, we need to pick a machine625 ** dependent value. This is only for standard user threads. For custom threads,626 ** 0 has a special meaning.627 ** Adjust stackSize. Round up to a page boundary.628 */629 630 #ifndef _MD_MINIMUM_STACK_SIZE631 #define _MD_MINIMUM_STACK_SIZE 0632 #endif633 634 #if (!defined(HAVE_CUSTOM_USER_THREADS))635 #define _PR_ADJUST_STACKSIZE(stackSize) \636 PR_BEGIN_MACRO \637 if (stackSize == 0) \638 stackSize = _MD_DEFAULT_STACK_SIZE; \639 if (stackSize < _MD_MINIMUM_STACK_SIZE) \640 stackSize = _MD_MINIMUM_STACK_SIZE; \641 stackSize = (stackSize + (1 << _pr_pageShift) - 1) >> _pr_pageShift; \642 stackSize <<= _pr_pageShift; \643 PR_END_MACRO644 #else645 #define _PR_ADJUST_STACKSIZE(stackSize)646 #endif647 648 #define _PR_IS_GCABLE_THREAD(thr) ((thr)->flags & _PR_GCABLE_THREAD)649 650 #define _PR_PENDING_INTERRUPT(thr) \651 (!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT))652 #define _PR_THREAD_BLOCK_INTERRUPT(thr) \653 (thr->flags |= _PR_INTERRUPT_BLOCKED)654 #define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \655 (thr->flags &= ~_PR_INTERRUPT_BLOCKED)656 657 #define _PR_THREAD_PTR(_qp) \658 ((PRThread*) ((char*) (_qp) - offsetof(PRThread,links)))659 660 #define _PR_ACTIVE_THREAD_PTR(_qp) \661 ((PRThread*) ((char*) (_qp) - offsetof(PRThread,active)))662 663 #define _PR_THREAD_CONDQ_PTR(_qp) \664 ((PRThread*) ((char*) (_qp) - offsetof(PRThread,waitQLinks)))665 666 #define _PR_THREAD_MD_TO_PTR(_md) \667 ((PRThread*) ((char*) (_md) - offsetof(PRThread,md)))668 669 #define _PR_THREAD_STACK_TO_PTR(_stack) \670 ((PRThread*) (_stack->thr))671 672 extern PRCList _pr_active_local_threadQ;673 extern PRCList _pr_active_global_threadQ;674 extern PRCList _pr_cpuQ;675 extern _MDLock _pr_cpuLock;676 extern PRInt32 _pr_md_idle_cpus;677 678 #define _PR_ACTIVE_LOCAL_THREADQ() _pr_active_local_threadQ679 #define _PR_ACTIVE_GLOBAL_THREADQ() _pr_active_global_threadQ680 #define _PR_CPUQ() _pr_cpuQ681 #define _PR_RUNQ(_cpu) ((_cpu)->queue->runQ)682 #define _PR_RUNQREADYMASK(_cpu) ((_cpu)->queue->runQReadyMask)683 #define _PR_SLEEPQ(_cpu) ((_cpu)->queue->sleepQ)684 #define _PR_SLEEPQMAX(_cpu) ((_cpu)->queue->sleepQmax)685 #define _PR_PAUSEQ(_cpu) ((_cpu)->queue->pauseQ)686 #define _PR_SUSPENDQ(_cpu) ((_cpu)->queue->suspendQ)687 #define _PR_WAITINGTOJOINQ(_cpu) ((_cpu)->queue->waitingToJoinQ)688 689 extern PRUint32 _pr_recycleThreads; /* Flag for behavior on thread cleanup */690 extern PRLock *_pr_deadQLock;691 extern PRUint32 _pr_numNativeDead;692 extern PRUint32 _pr_numUserDead;693 extern PRCList _pr_deadNativeQ;694 extern PRCList _pr_deadUserQ;695 #define _PR_DEADNATIVEQ _pr_deadNativeQ696 #define _PR_DEADUSERQ _pr_deadUserQ697 #define _PR_DEADQ_LOCK PR_Lock(_pr_deadQLock);698 #define _PR_DEADQ_UNLOCK PR_Unlock(_pr_deadQLock);699 #define _PR_INC_DEADNATIVE (_pr_numNativeDead++)700 #define _PR_DEC_DEADNATIVE (_pr_numNativeDead--)701 #define _PR_NUM_DEADNATIVE (_pr_numNativeDead)702 #define _PR_INC_DEADUSER (_pr_numUserDead++)703 #define _PR_DEC_DEADUSER (_pr_numUserDead--)704 #define _PR_NUM_DEADUSER (_pr_numUserDead)705 706 extern PRUint32 _pr_utid;707 708 extern struct _PRCPU *_pr_primordialCPU;709 710 extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */711 extern PRInt32 _pr_userActive; /* number of active user threads */712 extern PRInt32 _pr_systemActive; /* number of active system threads */713 extern PRInt32 _pr_primordialExitCount; /* number of user threads left714 * before the primordial thread715 * can exit. */716 extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for717 * notifying the primordial thread718 * when all other user threads719 * have terminated. */720 721 extern PRUintn _pr_maxPTDs;722 723 extern PRLock *_pr_terminationCVLock;724 725 /*************************************************************************726 * Internal routines either called by PR itself or from machine-dependent *727 * code. *728 *************************************************************************/729 730 extern void _PR_ClockInterrupt(void);731 732 extern void _PR_Schedule(void);733 extern void _PR_SetThreadPriority(734 PRThread* thread, PRThreadPriority priority);735 736 /***********************************************************************737 ** FUNCTION: _PR_NewSegment()738 ** DESCRIPTION:739 ** Allocate a memory segment. The "size" value is rounded up to the740 ** native system page size and a page aligned portion of memory is741 ** returned. This memory is not part of the malloc heap. If "vaddr" is742 ** not NULL then PR tries to allocate the segment at the desired virtual743 ** address.744 ** INPUTS: size: size of the desired memory segment745 ** vaddr: address at which the newly aquired segment is to be746 ** mapped into memory.747 ** OUTPUTS: a memory segment is allocated, a PRSegment is allocated748 ** RETURN: pointer to PRSegment749 ***********************************************************************/750 extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr);751 752 /***********************************************************************753 ** FUNCTION: _PR_DestroySegment()754 ** DESCRIPTION:755 ** The memory segment and the PRSegment are freed756 ** INPUTS: seg: pointer to PRSegment to be freed757 ** OUTPUTS: the the PRSegment and its associated memory segment are freed758 ** RETURN: void759 ***********************************************************************/760 extern void _PR_DestroySegment(PRSegment *seg);761 762 extern PRThreadStack * _PR_NewStack(PRUint32 stackSize);763 extern void _PR_FreeStack(PRThreadStack *stack);764 extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me);765 extern void _PR_NotifyLockedThread (PRThread *thread);766 767 NSPR_API(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout);768 NSPR_API(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time);769 770 extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread);771 772 NSPR_API(PRThread*) _PR_CreateThread(PRThreadType type,773 void (*start)(void *arg),774 void *arg,775 PRThreadPriority priority,776 PRThreadScope scope,777 PRThreadState state,778 PRUint32 stackSize,779 PRUint32 flags);780 781 extern void _PR_NativeDestroyThread(PRThread *thread);782 extern void _PR_UserDestroyThread(PRThread *thread);783 784 extern PRThread* _PRI_AttachThread(785 PRThreadType type, PRThreadPriority priority,786 PRThreadStack *stack, PRUint32 flags);787 788 extern void _PRI_DetachThread(void);789 790 791 #define _PR_IO_PENDING(_thread) ((_thread)->io_pending)792 793 NSPR_API(void) _PR_MD_INIT_CPUS();794 #define _PR_MD_INIT_CPUS _MD_INIT_CPUS795 796 NSPR_API(void) _PR_MD_WAKEUP_CPUS();797 #define _PR_MD_WAKEUP_CPUS _MD_WAKEUP_CPUS798 799 /* Interrupts related */800 801 NSPR_API(void) _PR_MD_START_INTERRUPTS(void);802 #define _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS803 804 NSPR_API(void) _PR_MD_STOP_INTERRUPTS(void);805 #define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS806 807 NSPR_API(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void);808 #define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS809 810 NSPR_API(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);811 #define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS812 813 NSPR_API(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);814 #define _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS815 816 NSPR_API(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);817 #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS818 819 /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and820 * awaken a thread which is waiting on a lock or cvar.821 */822 extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout);823 #define _PR_MD_WAIT _MD_WAIT824 825 extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *);826 #define _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER827 828 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */829 NSPR_API(void) _PR_MD_CLOCK_INTERRUPT(void);830 #define _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT831 #endif832 833 /* Stack debugging */834 NSPR_API(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);835 #define _PR_MD_INIT_STACK _MD_INIT_STACK836 837 NSPR_API(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);838 #define _PR_MD_CLEAR_STACK _MD_CLEAR_STACK839 840 /* CPU related */841 NSPR_API(PRInt32) _PR_MD_GET_INTSOFF(void);842 #define _PR_MD_GET_INTSOFF _MD_GET_INTSOFF843 844 NSPR_API(void) _PR_MD_SET_INTSOFF(PRInt32 _val);845 #define _PR_MD_SET_INTSOFF _MD_SET_INTSOFF846 847 NSPR_API(_PRCPU*) _PR_MD_CURRENT_CPU(void);848 #define _PR_MD_CURRENT_CPU _MD_CURRENT_CPU849 850 NSPR_API(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);851 #define _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU852 853 NSPR_API(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);854 #define _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU855 856 /*857 * Returns the number of threads awoken or 0 if a timeout occurred;858 */859 extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout);860 #define _PR_MD_PAUSE_CPU _MD_PAUSE_CPU861 862 extern void _PR_MD_CLEANUP_BEFORE_EXIT(void);863 #define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT864 865 extern void _PR_MD_EXIT(PRIntn status);866 #define _PR_MD_EXIT _MD_EXIT867 868 /* Locks related */869 870 NSPR_API(void) _PR_MD_INIT_LOCKS(void);871 #define _PR_MD_INIT_LOCKS _MD_INIT_LOCKS872 873 NSPR_API(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md);874 #define _PR_MD_NEW_LOCK _MD_NEW_LOCK875 876 NSPR_API(void) _PR_MD_FREE_LOCK(_MDLock *md);877 #define _PR_MD_FREE_LOCK _MD_FREE_LOCK878 879 NSPR_API(void) _PR_MD_LOCK(_MDLock *md);880 #define _PR_MD_LOCK _MD_LOCK881 882 /* Return 0 on success, a nonzero value on failure. */883 NSPR_API(PRIntn) _PR_MD_TEST_AND_LOCK(_MDLock *md);884 #define _PR_MD_TEST_AND_LOCK _MD_TEST_AND_LOCK885 886 NSPR_API(void) _PR_MD_UNLOCK(_MDLock *md);887 #define _PR_MD_UNLOCK _MD_UNLOCK888 889 NSPR_API(void) _PR_MD_IOQ_LOCK(void);890 #define _PR_MD_IOQ_LOCK _MD_IOQ_LOCK891 892 NSPR_API(void) _PR_MD_IOQ_UNLOCK(void);893 #define _PR_MD_IOQ_UNLOCK _MD_IOQ_UNLOCK894 895 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */896 /* Semaphore related -- only for native threads */897 #ifdef HAVE_CVAR_BUILT_ON_SEM898 NSPR_API(void) _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value);899 #define _PR_MD_NEW_SEM _MD_NEW_SEM900 901 NSPR_API(void) _PR_MD_DESTROY_SEM(_MDSemaphore *md);902 #define _PR_MD_DESTROY_SEM _MD_DESTROY_SEM903 904 NSPR_API(PRStatus) _PR_MD_TIMED_WAIT_SEM(905 _MDSemaphore *md, PRIntervalTime timeout);906 #define _PR_MD_TIMED_WAIT_SEM _MD_TIMED_WAIT_SEM907 908 NSPR_API(PRStatus) _PR_MD_WAIT_SEM(_MDSemaphore *md);909 #define _PR_MD_WAIT_SEM _MD_WAIT_SEM910 911 NSPR_API(void) _PR_MD_POST_SEM(_MDSemaphore *md);912 #define _PR_MD_POST_SEM _MD_POST_SEM913 #endif /* HAVE_CVAR_BUILT_ON_SEM */914 915 #endif916 917 /* Condition Variables related -- only for native threads */918 919 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */920 NSPR_API(PRInt32) _PR_MD_NEW_CV(_MDCVar *md);921 #define _PR_MD_NEW_CV _MD_NEW_CV922 923 NSPR_API(void) _PR_MD_FREE_CV(_MDCVar *md);924 #define _PR_MD_FREE_CV _MD_FREE_CV925 926 NSPR_API(void) _PR_MD_WAIT_CV(927 _MDCVar *mdCVar,_MDLock *mdLock,PRIntervalTime timeout);928 #define _PR_MD_WAIT_CV _MD_WAIT_CV929 930 NSPR_API(void) _PR_MD_NOTIFY_CV(_MDCVar *md, _MDLock *lock);931 #define _PR_MD_NOTIFY_CV _MD_NOTIFY_CV932 933 NSPR_API(void) _PR_MD_NOTIFYALL_CV(_MDCVar *md, _MDLock *lock);934 #define _PR_MD_NOTIFYALL_CV _MD_NOTIFYALL_CV935 #endif /* _PR_LOCAL_THREADS_ONLY */936 937 /* Threads related */938 NSPR_API(PRThread*) _PR_MD_CURRENT_THREAD(void);939 #define _PR_MD_CURRENT_THREAD _MD_CURRENT_THREAD940 941 NSPR_API(PRThread*) _PR_MD_GET_ATTACHED_THREAD(void);942 #define _PR_MD_GET_ATTACHED_THREAD _MD_GET_ATTACHED_THREAD943 944 NSPR_API(PRThread*) _PR_MD_LAST_THREAD(void);945 #define _PR_MD_LAST_THREAD _MD_LAST_THREAD946 947 NSPR_API(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread);948 #define _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD949 950 NSPR_API(void) _PR_MD_SET_LAST_THREAD(PRThread *thread);951 #define _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD952 953 extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread);954 #define _PR_MD_INIT_THREAD _MD_INIT_THREAD955 956 extern void _PR_MD_EXIT_THREAD(PRThread *thread);957 #define _PR_MD_EXIT_THREAD _MD_EXIT_THREAD958 959 #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */960 961 NSPR_API(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread);962 #define _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD963 964 extern void _PR_MD_SUSPEND_THREAD(PRThread *thread);965 #define _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD966 967 extern void _PR_MD_RESUME_THREAD(PRThread *thread);968 #define _PR_MD_RESUME_THREAD _MD_RESUME_THREAD969 970 extern void _PR_MD_SUSPEND_CPU(_PRCPU *cpu);971 #define _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU972 973 extern void _PR_MD_RESUME_CPU(_PRCPU *cpu);974 #define _PR_MD_RESUME_CPU _MD_RESUME_CPU975 976 extern void _PR_MD_BEGIN_SUSPEND_ALL(void);977 #define _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL978 979 extern void _PR_MD_END_SUSPEND_ALL(void);980 #define _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL981 982 extern void _PR_MD_BEGIN_RESUME_ALL(void);983 #define _PR_MD_BEGIN_RESUME_ALL _MD_BEGIN_RESUME_ALL984 985 extern void _PR_MD_END_RESUME_ALL(void);986 #define _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL987 988 #if defined(IRIX)989 NSPR_API(void) _PR_IRIX_CHILD_PROCESS(void);990 #endif /* IRIX */991 992 #endif /* !_PR_LOCAL_THREADS_ONLY */993 994 extern void _PR_MD_CLEAN_THREAD(PRThread *thread);995 #define _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD996 997 #ifdef HAVE_CUSTOM_USER_THREADS998 extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *);999 #define _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD1000 1001 extern PRThread* _PR_MD_CREATE_USER_THREAD(1002 PRUint32 stacksize,1003 void (*start)(void *),1004 void *arg);1005 #define _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD1006 #endif1007 1008 extern PRStatus _PR_MD_CREATE_THREAD(1009 PRThread *thread,1010 void (*start) (void *),1011 PRThreadPriority priority,1012 PRThreadScope scope,1013 PRThreadState state,1014 PRUint32 stackSize);1015 #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD1016 1017 extern void _PR_MD_JOIN_THREAD(_MDThread *md);1018 #define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD1019 1020 extern void _PR_MD_END_THREAD(void);1021 #define _PR_MD_END_THREAD _MD_END_THREAD1022 1023 extern void _PR_MD_YIELD(void);1024 #define _PR_MD_YIELD _MD_YIELD1025 1026 extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);1027 #define _PR_MD_SET_PRIORITY _MD_SET_PRIORITY1028 1029 NSPR_API(void) _PR_MD_SUSPENDALL(void);1030 #define _PR_MD_SUSPENDALL _MD_SUSPENDALL1031 1032 NSPR_API(void) _PR_MD_RESUMEALL(void);1033 #define _PR_MD_RESUMEALL _MD_RESUMEALL1034 1035 extern void _PR_MD_INIT_CONTEXT(1036 PRThread *thread, char *top, void (*start) (void), PRBool *status);1037 #define _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT1038 1039 extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread);1040 #define _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT1041 1042 extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread);1043 #define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT1044 1045 /* Segment related */1046 extern void _PR_MD_INIT_SEGS(void);1047 #define _PR_MD_INIT_SEGS _MD_INIT_SEGS1048 1049 extern PRStatus _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);1050 #define _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT1051 1052 extern void _PR_MD_FREE_SEGMENT(PRSegment *seg);1053 #define _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT1054 1055 /* Directory enumeration related */1056 extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name);1057 #define _PR_MD_OPEN_DIR _MD_OPEN_DIR1058 1059 extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags);1060 #define _PR_MD_READ_DIR _MD_READ_DIR1061 1062 extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md);1063 #define _PR_MD_CLOSE_DIR _MD_CLOSE_DIR1064 1065 /* Named semaphores related */1066 extern PRSem * _PR_MD_OPEN_SEMAPHORE(1067 const char *osname, PRIntn flags, PRIntn mode, PRUintn value);1068 #define _PR_MD_OPEN_SEMAPHORE _MD_OPEN_SEMAPHORE1069 1070 extern PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem);1071 #define _PR_MD_WAIT_SEMAPHORE _MD_WAIT_SEMAPHORE1072 1073 extern PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem);1074 #define _PR_MD_POST_SEMAPHORE _MD_POST_SEMAPHORE1075 1076 extern PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem);1077 #define _PR_MD_CLOSE_SEMAPHORE _MD_CLOSE_SEMAPHORE1078 1079 extern PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname);1080 #define _PR_MD_DELETE_SEMAPHORE _MD_DELETE_SEMAPHORE1081 1082 /* I/O related */1083 extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd);1084 #define _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC1085 1086 #ifdef XP_MAC1087 extern void _PR_MD_FREE_FILEDESC(PRFileDesc *fd);1088 #define _PR_MD_FREE_FILEDESC _MD_FREE_FILEDESC1089 #endif1090 1091 extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd);1092 #define _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK1093 1094 /* File I/O related */1095 extern PRInt32 _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode);1096 #define _PR_MD_OPEN _MD_OPEN1097 1098 extern PRInt32 _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode);1099 #define _PR_MD_OPEN_FILE _MD_OPEN_FILE1100 1101 extern PRInt32 _PR_MD_CLOSE_FILE(PRInt32 osfd);1102 #define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE1103 1104 extern PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 amount);1105 #define _PR_MD_READ _MD_READ1106 1107 extern PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 amount);1108 #define _PR_MD_WRITE _MD_WRITE1109 1110 extern PRInt32 _PR_MD_WRITEV(1111 PRFileDesc *fd, const struct PRIOVec *iov,1112 PRInt32 iov_size, PRIntervalTime timeout);1113 #define _PR_MD_WRITEV _MD_WRITEV1114 1115 extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd);1116 #define _PR_MD_FSYNC _MD_FSYNC1117 1118 extern PRInt32 _PR_MD_DELETE(const char *name);1119 #define _PR_MD_DELETE _MD_DELETE1120 1121 extern PRInt32 _PR_MD_RENAME(const char *from, const char *to);1122 #define _PR_MD_RENAME _MD_RENAME1123 1124 extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how);1125 #define _PR_MD_ACCESS _MD_ACCESS1126 1127 extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf);1128 #define _PR_MD_STAT _MD_STAT1129 1130 extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode);1131 #define _PR_MD_MKDIR _MD_MKDIR1132 1133 extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode);1134 #define _PR_MD_MAKE_DIR _MD_MAKE_DIR1135 1136 extern PRInt32 _PR_MD_RMDIR(const char *name);1137 #define _PR_MD_RMDIR _MD_RMDIR1138 1139 #ifdef MOZ_UNICODE1140 /* UTF16 File I/O related */1141 extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name);1142 #define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF161143 1144 extern PRInt32 _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode);1145 #define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF161146 1147 extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags);1148 #define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF161149 1150 extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md);1151 #define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF161152 1153 extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info);1154 #define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF161155 #endif /* MOZ_UNICODE */1156 1157 /* Socket I/O related */1158 extern void _PR_MD_INIT_IO(void);1159 #define _PR_MD_INIT_IO _MD_INIT_IO1160 1161 extern PRInt32 _PR_MD_CLOSE_SOCKET(PRInt32 osfd);1162 #define _PR_MD_CLOSE_SOCKET _MD_CLOSE_SOCKET1163 1164 extern PRInt32 _PR_MD_CONNECT(1165 PRFileDesc *fd, const PRNetAddr *addr,1166 PRUint32 addrlen, PRIntervalTime timeout);1167 #define _PR_MD_CONNECT _MD_CONNECT1168 1169 extern PRInt32 _PR_MD_ACCEPT(1170 PRFileDesc *fd, PRNetAddr *addr,1171 PRUint32 *addrlen, PRIntervalTime timeout);1172 #define _PR_MD_ACCEPT _MD_ACCEPT1173 1174 extern PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen);1175 #define _PR_MD_BIND _MD_BIND1176 1177 extern PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog);1178 #define _PR_MD_LISTEN _MD_LISTEN1179 1180 extern PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how);1181 #define _PR_MD_SHUTDOWN _MD_SHUTDOWN1182 1183 extern PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount,1184 PRIntn flags, PRIntervalTime timeout);1185 #define _PR_MD_RECV _MD_RECV1186 1187 extern PRInt32 _PR_MD_SEND(1188 PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,1189 PRIntervalTime timeout);1190 #define _PR_MD_SEND _MD_SEND1191 1192 extern PRInt32 _PR_MD_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock,1193 PRNetAddr **raddr, void *buf, PRInt32 amount,1194 PRIntervalTime timeout);1195 #define _PR_MD_ACCEPT_READ _MD_ACCEPT_READ1196 1197 #ifdef WIN321198 extern PRInt32 _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *addr,1199 PRUint32 *addrlen, PRIntervalTime timeout,1200 PRBool fast,1201 _PR_AcceptTimeoutCallback callback,1202 void *callbackArg);1203 1204 extern PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock,1205 PRNetAddr **raddr, void *buf, PRInt32 amount,1206 PRIntervalTime timeout, PRBool fast,1207 _PR_AcceptTimeoutCallback callback,1208 void *callbackArg);1209 1210 extern void _PR_MD_UPDATE_ACCEPT_CONTEXT(PRInt32 s, PRInt32 ls);1211 #define _PR_MD_UPDATE_ACCEPT_CONTEXT _MD_UPDATE_ACCEPT_CONTEXT1212 #endif /* WIN32 */1213 1214 extern PRInt32 _PR_MD_SENDFILE(1215 PRFileDesc *sock, PRSendFileData *sfd,1216 PRInt32 flags, PRIntervalTime timeout);1217 #define _PR_MD_SENDFILE _MD_SENDFILE1218 1219 extern PRStatus _PR_MD_GETSOCKNAME(1220 PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);1221 #define _PR_MD_GETSOCKNAME _MD_GETSOCKNAME1222 1223 extern PRStatus _PR_MD_GETPEERNAME(1224 PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);1225 #define _PR_MD_GETPEERNAME _MD_GETPEERNAME1226 1227 extern PRStatus _PR_MD_GETSOCKOPT(1228 PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen);1229 #define _PR_MD_GETSOCKOPT _MD_GETSOCKOPT1230 1231 extern PRStatus _PR_MD_SETSOCKOPT(1232 PRFileDesc *fd, PRInt32 level, PRInt32 optname,1233 const char* optval, PRInt32 optlen);1234 #define _PR_MD_SETSOCKOPT _MD_SETSOCKOPT1235 1236 extern PRStatus PR_CALLBACK _PR_SocketGetSocketOption(1237 PRFileDesc *fd, PRSocketOptionData *data);1238 1239 extern PRStatus PR_CALLBACK _PR_SocketSetSocketOption(1240 PRFileDesc *fd, const PRSocketOptionData *data);1241 1242 extern PRInt32 _PR_MD_RECVFROM(1243 PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,1244 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout);1245 #define _PR_MD_RECVFROM _MD_RECVFROM1246 1247 extern PRInt32 _PR_MD_SENDTO(1248 PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,1249 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout);1250 #define _PR_MD_SENDTO _MD_SENDTO1251 1252 extern PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd);1253 #define _PR_MD_SOCKETPAIR _MD_SOCKETPAIR1254 1255 extern PRInt32 _PR_MD_SOCKET(int af, int type, int flags);1256 #define _PR_MD_SOCKET _MD_SOCKET1257 1258 extern PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd);1259 #define _PR_MD_SOCKETAVAILABLE _MD_SOCKETAVAILABLE1260 1261 extern PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd);1262 #define _PR_MD_PIPEAVAILABLE _MD_PIPEAVAILABLE1263 1264 extern PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds,1265 PRIntervalTime timeout);1266 #define _PR_MD_PR_POLL _MD_PR_POLL1267 1268 /*1269 * Initialize fd->secret->inheritable for a newly created fd.1270 * If 'imported' is false, the osfd (i.e., fd->secret->md.osfd)1271 * was created by NSPR and hence has the OS-dependent default1272 * inheritable attribute. If 'imported' is true, the osfd was1273 * not created by NSPR and hence a system call is required to1274 * query its inheritable attribute. Since we may never need to1275 * know the inheritable attribute of a fd, a platform may choose1276 * to initialize fd->secret->inheritable of an imported fd to1277 * _PR_TRI_UNKNOWN and only pay the cost of the system call1278 * (in _PR_MD_QUERY_FD_INHERITABLE) when necessary.1279 */1280 extern void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported);1281 #define _PR_MD_INIT_FD_INHERITABLE _MD_INIT_FD_INHERITABLE1282 1283 extern PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable);1284 #define _PR_MD_SET_FD_INHERITABLE _MD_SET_FD_INHERITABLE1285 1286 1287 #define _PR_PROCESS_TIMEOUT_INTERRUPT_ERRORS(me) \1288 if (_PR_PENDING_INTERRUPT(me)) { \1289 me->flags &= ~_PR_INTERRUPT; \1290 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); \1291 } else { \1292 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); \1293 }1294 1295 extern void *_PR_MD_GET_SP(PRThread *thread);1296 #define _PR_MD_GET_SP _MD_GET_SP1297 1298 #endif /* defined(_PR_PTHREADS) */1299 207 1300 208 /************************************************************************/ … … 1431 339 1432 340 struct PRLock { 1433 #if defined(_PR_PTHREADS)1434 341 pthread_mutex_t mutex; /* the underlying lock */ 1435 342 _PT_Notified notified; /* array of conditions notified */ 1436 343 PRBool locked; /* whether the mutex is locked */ 1437 344 pthread_t owner; /* if locked, current lock owner */ 1438 #elif defined(_PR_BTHREADS)1439 sem_id semaphoreID; /* the underlying lock */1440 int32 benaphoreCount; /* number of people in lock */1441 thread_id owner; /* current lock owner */1442 #else /* not pthreads or Be threads */1443 PRCList links; /* linkage for PRThread.lockList */1444 struct PRThread *owner; /* current lock owner */1445 PRCList waitQ; /* list of threads waiting for lock */1446 PRThreadPriority priority; /* priority of lock */1447 PRThreadPriority boostPriority; /* boosted priority of lock owner */1448 _MDLock ilock; /* Internal Lock to protect user-level fields */1449 #endif1450 345 }; 1451 346 … … 1454 349 struct PRCondVar { 1455 350 PRLock *lock; /* associated lock that protects the condition */ 1456 #if defined(_PR_PTHREADS)1457 351 pthread_cond_t cv; /* underlying pthreads condition */ 1458 352 PRInt32 notify_pending; /* CV has destroy pending notification */ 1459 #elif defined(_PR_BTHREADS)1460 sem_id sem; /* the underlying lock */1461 sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */1462 sem_id signalSem; /* the lock for threads waiting for someone to notify */1463 volatile int32 nw; /* the number waiting */1464 volatile int32 ns; /* the number signalling */1465 long signalBenCount; /* the number waiting on the underlying sem */1466 #else /* not pthreads or Be threads */1467 PRCList condQ; /* Condition variable wait Q */1468 _MDLock ilock; /* Internal Lock to protect condQ */1469 _MDCVar md;1470 #endif1471 353 }; 1472 354 … … 1475 357 struct PRMonitor { 1476 358 const char* name; /* monitor name for debugging */ 1477 #if defined(_PR_PTHREADS)1478 359 PRLock lock; /* the lock structure */ 1479 360 pthread_t owner; /* the owner of the lock or invalid */ 1480 361 PRCondVar *cvar; /* condition variable queue */ 1481 #else /* defined(_PR_PTHREADS) */1482 PRCondVar *cvar; /* associated lock and condition variable queue */1483 #endif /* defined(_PR_PTHREADS) */1484 362 PRUint32 entryCount; /* # of times re-entered */ 1485 363 }; … … 1488 366 1489 367 struct PRSemaphore { 1490 #if defined(_PR_BTHREADS)1491 sem_id sem;1492 int32 benaphoreCount;1493 #else1494 368 PRCondVar *cvar; /* associated lock and condition variable queue */ 1495 369 PRUintn count; /* the value of the counting semaphore */ 1496 370 PRUint32 waiters; /* threads waiting on the semaphore */ 1497 #if defined(_PR_PTHREADS)1498 #else /* defined(_PR_PTHREADS) */1499 _MDSemaphore md;1500 #endif /* defined(_PR_PTHREADS) */1501 #endif /* defined(_PR_BTHREADS) */1502 371 }; 1503 372 … … 1547 416 PRSegment *seg; 1548 417 PRThread* thr; /* back pointer to thread owning this stack */ 1549 1550 #if defined(_PR_PTHREADS)1551 #else /* defined(_PR_PTHREADS) */1552 _MDThreadStack md;1553 #endif /* defined(_PR_PTHREADS) */1554 418 }; 1555 419 … … 1582 446 char *errorString; /* current error string | NULL */ 1583 447 1584 #if defined(_PR_PTHREADS)1585 448 pthread_t id; /* pthread identifier for the thread */ 1586 449 PRBool okToDelete; /* ok to delete the PRThread struct? */ … … 1599 462 int *selectfd_list; /* Unix fd's that PR_Poll selects on */ 1600 463 PRUint32 selectfd_count; /* number of elements in selectfd_list */ 1601 #endif1602 #elif defined(_PR_BTHREADS)1603 PRUint32 flags;1604 _MDThread md;1605 PRBool io_pending;1606 PRInt32 io_fd;1607 PRBool io_suspended;1608 #else /* not pthreads or Be threads */1609 _MDLock threadLock; /* Lock to protect thread state variables.1610 * Protects the following fields:1611 * state1612 * priority1613 * links1614 * wait1615 * cpu1616 */1617 PRUint32 queueCount;1618 PRUint32 waitCount;1619 1620 PRCList active; /* on list of all active threads */1621 PRCList links;1622 PRCList waitQLinks; /* when thread is PR_Wait'ing */1623 PRCList lockList; /* list of locks currently holding */1624 PRIntervalTime sleep; /* sleep time when thread is sleeping */1625 struct _wait {1626 struct PRLock *lock;1627 struct PRCondVar *cvar;1628 } wait;1629 1630 PRUint32 id;1631 PRUint32 flags;1632 PRUint32 no_sched; /* Don't schedule the thread to run.1633 * This flag has relevance only when1634 * multiple NSPR CPUs are created.1635 * When a thread is de-scheduled, there1636 * is a narrow window of time in which1637 * the thread is put on the run queue1638 * but the scheduler is actually using1639 * the stack of this thread. It is safe1640 * to run this thread on a different CPU1641 * only when its stack is not in use on1642 * any other CPU. The no_sched flag is1643 * set during this interval to prevent1644 * the thread from being scheduled on a1645 * different CPU.1646 */1647 1648 /* thread termination condition variable for join */1649 PRCondVar *term;1650 1651 _PRCPU *cpu; /* cpu to which this thread is bound */1652 PRUint32 threadAllocatedOnStack;/* boolean */1653 1654 /* When an async IO is in progress and a second async IO cannot be1655 * initiated, the io_pending flag is set to true. Some platforms will1656 * not use the io_pending flag. If the io_pending flag is true, then1657 * io_fd is the OS-file descriptor on which IO is pending.1658 */1659 PRBool io_pending;1660 PRInt32 io_fd;1661 1662 /* If a timeout occurs or if an outstanding IO is interrupted and the1663 * OS doesn't support a real cancellation (NT or MAC), then the1664 * io_suspended flag will be set to true. The thread will be resumed1665 * but may run into trouble issuing additional IOs until the io_pending1666 * flag can be cleared1667 */1668 PRBool io_suspended;1669 1670 _MDThread md;1671 464 #endif 1672 465 }; … … 1803 596 PRUint32 size; 1804 597 PRUintn flags; 1805 #if defined(_PR_PTHREADS)1806 #else /* defined(_PR_PTHREADS) */1807 _MDSegment md;1808 #endif /* defined(_PR_PTHREADS) */1809 598 }; 1810 599 -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/prlog.c
r73071 r101805 72 72 */ 73 73 static PRLock *_pr_logLock; 74 #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)75 74 #define _PR_LOCK_LOG() PR_Lock(_pr_logLock); 76 75 #define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock); 77 #elif defined(_PR_GLOBAL_THREADS_ONLY)78 #define _PR_LOCK_LOG() { _PR_LOCK_LOCK(_pr_logLock)79 #define _PR_UNLOCK_LOG() _PR_LOCK_UNLOCK(_pr_logLock); }80 #else81 82 #define _PR_LOCK_LOG() \83 { \84 PRIntn _is; \85 PRThread *_me = _PR_MD_CURRENT_THREAD(); \86 if (!_PR_IS_NATIVE_THREAD(_me)) \87 _PR_INTSOFF(_is); \88 _PR_LOCK_LOCK(_pr_logLock)89 90 #define _PR_UNLOCK_LOG() \91 _PR_LOCK_UNLOCK(_pr_logLock); \92 PR_ASSERT(_me == _PR_MD_CURRENT_THREAD()); \93 if (!_PR_IS_NATIVE_THREAD(_me)) \94 _PR_INTSON(_is); \95 }96 97 #endif98 76 99 77 #if defined(XP_PC) -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/prmapopt.c
r1 r101805 74 74 #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */ 75 75 #endif 76 77 #ifndef _PR_PTHREADS78 79 PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)80 {81 PRStatus rv;82 PRInt32 length;83 PRInt32 level, name;84 85 /*86 * PR_SockOpt_Nonblocking is a special case that does not87 * translate to a getsockopt() call88 */89 if (PR_SockOpt_Nonblocking == data->option)90 {91 data->value.non_blocking = fd->secret->nonblocking;92 return PR_SUCCESS;93 }94 95 rv = _PR_MapOptionName(data->option, &level, &name);96 if (PR_SUCCESS == rv)97 {98 switch (data->option)99 {100 case PR_SockOpt_Linger:101 {102 #if !defined(XP_BEOS) || defined(BONE_VERSION)103 struct linger linger;104 length = sizeof(linger);105 rv = _PR_MD_GETSOCKOPT(106 fd, level, name, (char *) &linger, &length);107 if (PR_SUCCESS == rv)108 {109 PR_ASSERT(sizeof(linger) == length);110 data->value.linger.polarity =111 (linger.l_onoff) ? PR_TRUE : PR_FALSE;112 data->value.linger.linger =113 PR_SecondsToInterval(linger.l_linger);114 }115 break;116 #else117 PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );118 return PR_FAILURE;119 #endif120 }121 case PR_SockOpt_Reuseaddr:122 case PR_SockOpt_Keepalive:123 case PR_SockOpt_NoDelay:124 case PR_SockOpt_Broadcast:125 {126 #ifdef WIN32 /* Winsock */127 BOOL value;128 #else129 PRIntn value;130 #endif131 length = sizeof(value);132 rv = _PR_MD_GETSOCKOPT(133 fd, level, name, (char*)&value, &length);134 if (PR_SUCCESS == rv)135 data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;136 break;137 }138 case PR_SockOpt_McastLoopback:139 {140 #ifdef WIN32 /* Winsock */141 BOOL bool;142 #else143 PRUint8 bool;144 #endif145 length = sizeof(bool);146 rv = _PR_MD_GETSOCKOPT(147 fd, level, name, (char*)&bool, &length);148 if (PR_SUCCESS == rv)149 data->value.mcast_loopback = (0 == bool) ? PR_FALSE : PR_TRUE;150 break;151 }152 case PR_SockOpt_RecvBufferSize:153 case PR_SockOpt_SendBufferSize:154 case PR_SockOpt_MaxSegment:155 {156 PRIntn value;157 length = sizeof(value);158 rv = _PR_MD_GETSOCKOPT(159 fd, level, name, (char*)&value, &length);160 if (PR_SUCCESS == rv)161 data->value.recv_buffer_size = value;162 break;163 }164 case PR_SockOpt_IpTimeToLive:165 case PR_SockOpt_IpTypeOfService:166 {167 /* These options should really be an int (or PRIntn). */168 length = sizeof(PRUintn);169 rv = _PR_MD_GETSOCKOPT(170 fd, level, name, (char*)&data->value.ip_ttl, &length);171 break;172 }173 case PR_SockOpt_McastTimeToLive:174 {175 #ifdef WIN32 /* Winsock */176 int ttl;177 #else178 PRUint8 ttl;179 #endif180 length = sizeof(ttl);181 rv = _PR_MD_GETSOCKOPT(182 fd, level, name, (char*)&ttl, &length);183 if (PR_SUCCESS == rv)184 data->value.mcast_ttl = ttl;185 break;186 }187 #ifdef IP_ADD_MEMBERSHIP188 case PR_SockOpt_AddMember:189 case PR_SockOpt_DropMember:190 {191 struct ip_mreq mreq;192 length = sizeof(mreq);193 rv = _PR_MD_GETSOCKOPT(194 fd, level, name, (char*)&mreq, &length);195 if (PR_SUCCESS == rv)196 {197 data->value.add_member.mcaddr.inet.ip =198 mreq.imr_multiaddr.s_addr;199 data->value.add_member.ifaddr.inet.ip =200 mreq.imr_interface.s_addr;201 }202 break;203 }204 #endif /* IP_ADD_MEMBERSHIP */205 case PR_SockOpt_McastInterface:206 {207 /* This option is a struct in_addr. */208 length = sizeof(data->value.mcast_if.inet.ip);209 rv = _PR_MD_GETSOCKOPT(210 fd, level, name,211 (char*)&data->value.mcast_if.inet.ip, &length);212 break;213 }214 default:215 PR_NOT_REACHED("Unknown socket option");216 break;217 }218 }219 return rv;220 } /* _PR_SocketGetSocketOption */221 222 PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)223 {224 PRStatus rv;225 PRInt32 level, name;226 227 /*228 * PR_SockOpt_Nonblocking is a special case that does not229 * translate to a setsockopt call.230 */231 if (PR_SockOpt_Nonblocking == data->option)232 {233 #ifdef WINNT234 PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE)235 || (fd->secret->nonblocking == data->value.non_blocking));236 if (fd->secret->md.io_model_committed237 && (fd->secret->nonblocking != data->value.non_blocking))238 {239 /*240 * On NT, once we have associated a socket with the io241 * completion port, we can't disassociate it. So we242 * can't change the nonblocking option of the socket243 * afterwards.244 */245 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);246 return PR_FAILURE;247 }248 #endif249 fd->secret->nonblocking = data->value.non_blocking;250 return PR_SUCCESS;251 }252 253 rv = _PR_MapOptionName(data->option, &level, &name);254 if (PR_SUCCESS == rv)255 {256 switch (data->option)257 {258 case PR_SockOpt_Linger:259 {260 #if !defined(XP_BEOS) || defined(BONE_VERSION)261 struct linger linger;262 linger.l_onoff = data->value.linger.polarity;263 linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);264 rv = _PR_MD_SETSOCKOPT(265 fd, level, name, (char*)&linger, sizeof(linger));266 break;267 #else268 PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );269 return PR_FAILURE;270 #endif271 }272 case PR_SockOpt_Reuseaddr:273 case PR_SockOpt_Keepalive:274 case PR_SockOpt_NoDelay:275 case PR_SockOpt_Broadcast:276 {277 #ifdef WIN32 /* Winsock */278 BOOL value;279 #else280 PRIntn value;281 #endif282 value = (data->value.reuse_addr) ? 1 : 0;283 rv = _PR_MD_SETSOCKOPT(284 fd, level, name, (char*)&value, sizeof(value));285 break;286 }287 case PR_SockOpt_McastLoopback:288 {289 #ifdef WIN32 /* Winsock */290 BOOL bool;291 #else292 PRUint8 bool;293 #endif294 bool = data->value.mcast_loopback ? 1 : 0;295 rv = _PR_MD_SETSOCKOPT(296 fd, level, name, (char*)&bool, sizeof(bool));297 break;298 }299 case PR_SockOpt_RecvBufferSize:300 case PR_SockOpt_SendBufferSize:301 case PR_SockOpt_MaxSegment:302 {303 PRIntn value = data->value.recv_buffer_size;304 rv = _PR_MD_SETSOCKOPT(305 fd, level, name, (char*)&value, sizeof(value));306 break;307 }308 case PR_SockOpt_IpTimeToLive:309 case PR_SockOpt_IpTypeOfService:310 {311 /* These options should really be an int (or PRIntn). */312 rv = _PR_MD_SETSOCKOPT(313 fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn));314 break;315 }316 case PR_SockOpt_McastTimeToLive:317 {318 #ifdef WIN32 /* Winsock */319 int ttl;320 #else321 PRUint8 ttl;322 #endif323 ttl = data->value.mcast_ttl;324 rv = _PR_MD_SETSOCKOPT(325 fd, level, name, (char*)&ttl, sizeof(ttl));326 break;327 }328 #ifdef IP_ADD_MEMBERSHIP329 case PR_SockOpt_AddMember:330 case PR_SockOpt_DropMember:331 {332 struct ip_mreq mreq;333 mreq.imr_multiaddr.s_addr =334 data->value.add_member.mcaddr.inet.ip;335 mreq.imr_interface.s_addr =336 data->value.add_member.ifaddr.inet.ip;337 rv = _PR_MD_SETSOCKOPT(338 fd, level, name, (char*)&mreq, sizeof(mreq));339 break;340 }341 #endif /* IP_ADD_MEMBERSHIP */342 case PR_SockOpt_McastInterface:343 {344 /* This option is a struct in_addr. */345 rv = _PR_MD_SETSOCKOPT(346 fd, level, name, (char*)&data->value.mcast_if.inet.ip,347 sizeof(data->value.mcast_if.inet.ip));348 break;349 }350 default:351 PR_NOT_REACHED("Unknown socket option");352 break;353 }354 }355 return rv;356 } /* _PR_SocketSetSocketOption */357 358 #endif /* ! _PR_PTHREADS */359 76 360 77 /* -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/darwin.c
r1 r101805 44 44 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 45 45 { 46 #if !defined(_PR_PTHREADS)47 if (isCurrent) {48 (void) setjmp(CONTEXT(t));49 }50 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);51 return (PRWord *) CONTEXT(t);52 #else53 46 *np = 0; 54 47 return NULL; 55 #endif56 48 } 57 58 #if !defined(_PR_PTHREADS)59 void60 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)61 {62 return;63 }64 65 PRStatus66 _MD_InitializeThread(PRThread *thread)67 {68 return PR_SUCCESS;69 }70 71 PRStatus72 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)73 {74 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));75 _PR_MD_SWITCH_CONTEXT(thread);76 return PR_SUCCESS;77 }78 79 PRStatus80 _MD_WAKEUP_WAITER(PRThread *thread)81 {82 if (thread) {83 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));84 }85 return PR_SUCCESS;86 }87 88 /* These functions should not be called for Darwin */89 void90 _MD_YIELD(void)91 {92 PR_NOT_REACHED("_MD_YIELD should not be called for Darwin.");93 }94 95 PRStatus96 _MD_CREATE_THREAD(97 PRThread *thread,98 void (*start) (void *),99 PRThreadPriority priority,100 PRThreadScope scope,101 PRThreadState state,102 PRUint32 stackSize)103 {104 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Darwin.");105 return PR_FAILURE;106 }107 #endif /* ! _PR_PTHREADS */108 49 109 50 /* darwin.c */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/freebsd.c
r1 r101805 56 56 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 57 57 { 58 #ifndef _PR_PTHREADS59 if (isCurrent) {60 (void) sigsetjmp(CONTEXT(t), 1);61 }62 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);63 return (PRWord *) CONTEXT(t);64 #else65 58 *np = 0; 66 59 return NULL; 67 #endif68 60 } 69 61 70 #ifndef _PR_PTHREADS71 void72 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)73 {74 return;75 }76 77 PRStatus78 _MD_InitializeThread(PRThread *thread)79 {80 return PR_SUCCESS;81 }82 83 PRStatus84 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)85 {86 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));87 _PR_MD_SWITCH_CONTEXT(thread);88 return PR_SUCCESS;89 }90 91 PRStatus92 _MD_WAKEUP_WAITER(PRThread *thread)93 {94 if (thread) {95 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));96 }97 return PR_SUCCESS;98 }99 100 /* These functions should not be called for FreeBSD */101 void102 _MD_YIELD(void)103 {104 PR_NOT_REACHED("_MD_YIELD should not be called for FreeBSD.");105 }106 107 PRStatus108 _MD_CREATE_THREAD(109 PRThread *thread,110 void (*start) (void *),111 PRThreadPriority priority,112 PRThreadScope scope,113 PRThreadState state,114 PRUint32 stackSize)115 {116 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for FreeBSD.");117 return PR_FAILURE;118 }119 #endif /* ! _PR_PTHREADS */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/linux.c
r1 r101805 44 44 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 45 45 { 46 #ifndef _PR_PTHREADS47 if (isCurrent) {48 (void) setjmp(CONTEXT(t));49 }50 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);51 return (PRWord *) CONTEXT(t);52 #else53 46 *np = 0; 54 47 return NULL; 55 #endif56 48 } 57 58 #ifdef _PR_PTHREADS59 49 60 50 extern void _MD_unix_terminate_waitpid_daemon(void); … … 65 55 } 66 56 67 #else /* ! _PR_PTHREADS */68 69 void70 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)71 {72 return;73 }74 75 PRStatus76 _MD_InitializeThread(PRThread *thread)77 {78 /*79 * set the pointers to the stack-pointer and frame-pointer words in the80 * context structure; this is for debugging use.81 */82 thread->md.sp = _MD_GET_SP_PTR(thread);83 thread->md.fp = _MD_GET_FP_PTR(thread);84 return PR_SUCCESS;85 }86 87 PRStatus88 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)89 {90 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));91 _PR_MD_SWITCH_CONTEXT(thread);92 return PR_SUCCESS;93 }94 95 PRStatus96 _MD_WAKEUP_WAITER(PRThread *thread)97 {98 if (thread) {99 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));100 }101 return PR_SUCCESS;102 }103 104 /* These functions should not be called for Linux */105 void106 _MD_YIELD(void)107 {108 PR_NOT_REACHED("_MD_YIELD should not be called for Linux.");109 }110 111 PRStatus112 _MD_CREATE_THREAD(113 PRThread *thread,114 void (*start) (void *),115 PRThreadPriority priority,116 PRThreadScope scope,117 PRThreadState state,118 PRUint32 stackSize)119 {120 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Linux.");121 return PR_FAILURE;122 }123 #endif /* ! _PR_PTHREADS */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/netbsd.c
r1 r101805 58 58 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 59 59 { 60 #ifndef _PR_PTHREADS61 if (isCurrent) {62 (void) sigsetjmp(CONTEXT(t), 1);63 }64 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);65 return (PRWord *) CONTEXT(t);66 #else67 60 *np = 0; 68 61 return NULL; 69 #endif70 62 } 71 63 72 #ifndef _PR_PTHREADS73 void74 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)75 {76 return;77 }78 79 PRStatus80 _MD_InitializeThread(PRThread *thread)81 {82 return PR_SUCCESS;83 }84 85 PRStatus86 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)87 {88 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));89 _PR_MD_SWITCH_CONTEXT(thread);90 return PR_SUCCESS;91 }92 93 PRStatus94 _MD_WAKEUP_WAITER(PRThread *thread)95 {96 if (thread) {97 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));98 }99 return PR_SUCCESS;100 }101 102 /* These functions should not be called for NetBSD */103 void104 _MD_YIELD(void)105 {106 PR_NOT_REACHED("_MD_YIELD should not be called for NetBSD.");107 }108 109 PRStatus110 _MD_CREATE_THREAD(111 PRThread *thread,112 void (*start) (void *),113 PRThreadPriority priority,114 PRThreadScope scope,115 PRThreadState state,116 PRUint32 stackSize)117 {118 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for NetBSD.");119 return PR_FAILURE;120 }121 #endif /* ! _PR_PTHREADS */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openbsd.c
r1 r101805 58 58 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 59 59 { 60 #ifndef _PR_PTHREADS61 if (isCurrent) {62 (void) sigsetjmp(CONTEXT(t), 1);63 }64 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);65 return (PRWord *) CONTEXT(t);66 #else67 60 *np = 0; 68 61 return NULL; 69 #endif70 62 } 71 63 72 #ifndef _PR_PTHREADS73 void74 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)75 {76 return;77 }78 79 PRStatus80 _MD_InitializeThread(PRThread *thread)81 {82 return PR_SUCCESS;83 }84 85 PRStatus86 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)87 {88 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));89 _PR_MD_SWITCH_CONTEXT(thread);90 return PR_SUCCESS;91 }92 93 PRStatus94 _MD_WAKEUP_WAITER(PRThread *thread)95 {96 if (thread) {97 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));98 }99 return PR_SUCCESS;100 }101 102 /* These functions should not be called for OpenBSD */103 void104 _MD_YIELD(void)105 {106 PR_NOT_REACHED("_MD_YIELD should not be called for OpenBSD.");107 }108 109 PRStatus110 _MD_CREATE_THREAD(111 PRThread *thread,112 void (*start) (void *),113 PRThreadPriority priority,114 PRThreadScope scope,115 PRThreadState state,116 PRUint32 stackSize)117 {118 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OpenBSD.");119 return PR_FAILURE;120 }121 #endif /* ! _PR_PTHREADS */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/solaris.c
r1 r101805 75 75 } 76 76 77 #ifdef _PR_PTHREADS78 77 void _MD_EarlyInit(void) 79 78 { … … 85 84 return NULL; 86 85 } 87 #endif /* _PR_PTHREADS */88 86 89 87 #if !defined(i386) && !defined(IS_64) … … 636 634 } 637 635 638 #ifdef OLD_CODE639 640 void _MD_SuspendAll()641 {642 /* On solaris there are threads, and there are LWPs.643 * Calling _PR_DoSingleThread would freeze all of the threads bound to LWPs644 * but not necessarily stop all LWPs (for example if someone did645 * an attachthread of a thread which was not bound to an LWP).646 * So now go through all the LWPs for this process and freeze them.647 *648 * Note that if any thread which is capable of having the GC run on it must649 * had better be a LWP with a single bound thread on it. Otherwise, this650 * might not stop that thread from being run.651 */652 PRThread *current = _PR_MD_CURRENT_THREAD();653 prstatus_t status, lwpstatus;654 int result, index, lwp_fd;655 lwpid_t me = _lwp_self();656 int err;657 int lwp_main_proc_fd;658 659 solaris_preempt_off();660 661 /* run at highest prio so I cannot be preempted */662 thr_getprio(thr_self(), &gcprio);663 thr_setprio(thr_self(), 0x7fffffff);664 665 current->md.sp = (uint_t)&me; /* set my own stack pointer */666 667 if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) {668 PR_ASSERT(0);669 solaris_preempt_on();670 return; /* XXXMB ARGH, we're hosed! */671 }672 673 if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCSTATUS, &status)) < 0) {674 err = errno;675 PR_ASSERT(0);676 goto failure; /* XXXMB ARGH, we're hosed! */677 }678 679 num_lwps = status.pr_nlwp;680 681 if ( (all_lwps = (lwpid_t *)PR_MALLOC((num_lwps+1) * sizeof(lwpid_t)))==NULL) {682 PR_ASSERT(0);683 goto failure; /* XXXMB ARGH, we're hosed! */684 }685 686 if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCLWPIDS, all_lwps)) < 0) {687 PR_ASSERT(0);688 PR_DELETE(all_lwps);689 goto failure; /* XXXMB ARGH, we're hosed! */690 }691 692 for (index=0; index< num_lwps; index++) {693 if (all_lwps[index] != me) {694 if (_lwp_suspend(all_lwps[index]) < 0) {695 /* could happen if lwp exited */696 all_lwps[index] = me; /* dummy it up */697 }698 }699 }700 701 /* Turns out that lwp_suspend is not a blocking call.702 * Go through the list and make sure they are all stopped.703 */704 for (index=0; index< num_lwps; index++) {705 if (all_lwps[index] != me) {706 if ( (lwp_fd = solaris_open_lwp(all_lwps[index], lwp_main_proc_fd)) < 0) {707 PR_ASSERT(0);708 PR_DELETE(all_lwps);709 all_lwps = NULL;710 goto failure; /* XXXMB ARGH, we're hosed! */711 }712 713 if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {714 /* Hopefully the thread just died... */715 close(lwp_fd);716 continue;717 }718 while ( !(lwpstatus.pr_flags & PR_STOPPED) ) {719 if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {720 PR_ASSERT(0); /* ARGH SOMETHING WRONG! */721 break;722 }723 solaris_msec_sleep(1);724 }725 solaris_record_regs(&lwpstatus);726 close(lwp_fd);727 }728 }729 730 close(lwp_main_proc_fd);731 732 return;733 failure:734 solaris_preempt_on();735 thr_setprio(thr_self(), gcprio);736 close(lwp_main_proc_fd);737 return;738 }739 740 void _MD_ResumeAll()741 {742 int i;743 lwpid_t me = _lwp_self();744 745 for (i=0; i < num_lwps; i++) {746 if (all_lwps[i] == me)747 continue;748 if ( _lwp_continue(all_lwps[i]) < 0) {749 PR_ASSERT(0); /* ARGH, we are hosed! */750 }751 }752 753 /* restore priority and sigmask */754 thr_setprio(thr_self(), gcprio);755 solaris_preempt_on();756 PR_DELETE(all_lwps);757 all_lwps = NULL;758 }759 #endif /* OLD_CODE */760 761 636 #ifdef USE_SETJMP 762 637 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) … … 862 737 863 738 #endif /* _PR_GLOBAL_THREADS_ONLY */ 864 865 #ifndef _PR_PTHREADS866 #if defined(i386) && defined(SOLARIS2_4)867 /*868 * Because clock_gettime() on Solaris/x86 2.4 always generates a869 * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),870 * which is implemented using gettimeofday().871 */872 873 int874 _pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp)875 {876 struct timeval tv;877 878 if (clock_id != CLOCK_REALTIME) {879 errno = EINVAL;880 return -1;881 }882 883 gettimeofday(&tv, NULL);884 tp->tv_sec = tv.tv_sec;885 tp->tv_nsec = tv.tv_usec * 1000;886 return 0;887 }888 #endif /* i386 && SOLARIS2_4 */889 #endif /* _PR_PTHREADS */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix.c
r101749 r101805 97 97 sigset_t timer_set; 98 98 99 #if !defined(_PR_PTHREADS)100 101 static sigset_t empty_set;102 103 #ifdef SOLARIS104 #include <sys/file.h>105 #include <sys/filio.h>106 #endif107 108 #ifndef PIPE_BUF109 #define PIPE_BUF 512110 #endif111 112 /*113 * _nspr_noclock - if set clock interrupts are disabled114 */115 int _nspr_noclock = 1;116 117 #ifdef IRIX118 extern PRInt32 _nspr_terminate_on_error;119 #endif120 121 /*122 * There is an assertion in this code that NSPR's definition of PRIOVec123 * is bit compatible with UNIX' definition of a struct iovec. This is124 * applicable to the 'writev()' operations where the types are casually125 * cast to avoid warnings.126 */127 128 int _pr_md_pipefd[2] = { -1, -1 };129 static char _pr_md_pipebuf[PIPE_BUF];130 static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag,131 PRIntervalTime timeout);132 133 _PRInterruptTable _pr_interruptTable[] = {134 {135 "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },136 {137 0 }138 };139 140 PR_IMPLEMENT(void) _MD_unix_init_running_cpu(_PRCPU *cpu)141 {142 PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));143 cpu->md.md_unix.ioq_max_osfd = -1;144 cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;145 }146 147 PRStatus _MD_open_dir(_MDDir *d, const char *name)148 {149 int err;150 151 d->d = opendir(name);152 if (!d->d) {153 err = _MD_ERRNO();154 _PR_MD_MAP_OPENDIR_ERROR(err);155 return PR_FAILURE;156 }157 return PR_SUCCESS;158 }159 160 PRInt32 _MD_close_dir(_MDDir *d)161 {162 int rv = 0, err;163 164 if (d->d) {165 rv = closedir(d->d);166 if (rv == -1) {167 err = _MD_ERRNO();168 _PR_MD_MAP_CLOSEDIR_ERROR(err);169 }170 }171 return rv;172 }173 174 char * _MD_read_dir(_MDDir *d, PRIntn flags)175 {176 struct dirent *de;177 int err;178 179 for (;;) {180 /*181 * XXX: readdir() is not MT-safe. There is an MT-safe version182 * readdir_r() on some systems.183 */184 de = readdir(d->d);185 if (!de) {186 err = _MD_ERRNO();187 _PR_MD_MAP_READDIR_ERROR(err);188 return 0;189 }190 if ((flags & PR_SKIP_DOT) &&191 (de->d_name[0] == '.') && (de->d_name[1] == 0))192 continue;193 if ((flags & PR_SKIP_DOT_DOT) &&194 (de->d_name[0] == '.') && (de->d_name[1] == '.') &&195 (de->d_name[2] == 0))196 continue;197 if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.'))198 continue;199 break;200 }201 return de->d_name;202 }203 204 PRInt32 _MD_delete(const char *name)205 {206 PRInt32 rv, err;207 #ifdef UNIXWARE208 sigset_t set, oset;209 #endif210 211 #ifdef UNIXWARE212 sigfillset(&set);213 sigprocmask(SIG_SETMASK, &set, &oset);214 #endif215 rv = unlink(name);216 #ifdef UNIXWARE217 sigprocmask(SIG_SETMASK, &oset, NULL);218 #endif219 if (rv == -1) {220 err = _MD_ERRNO();221 _PR_MD_MAP_UNLINK_ERROR(err);222 }223 return(rv);224 }225 226 PRInt32 _MD_rename(const char *from, const char *to)227 {228 PRInt32 rv = -1, err;229 230 /*231 ** This is trying to enforce the semantics of WINDOZE' rename232 ** operation. That means one is not allowed to rename over top233 ** of an existing file. Holding a lock across these two function234 ** and the open function is known to be a bad idea, but ....235 */236 if (NULL != _pr_rename_lock)237 PR_Lock(_pr_rename_lock);238 if (0 == access(to, F_OK))239 PR_SetError(PR_FILE_EXISTS_ERROR, 0);240 else241 {242 rv = rename(from, to);243 if (rv < 0) {244 err = _MD_ERRNO();245 _PR_MD_MAP_RENAME_ERROR(err);246 }247 }248 if (NULL != _pr_rename_lock)249 PR_Unlock(_pr_rename_lock);250 return rv;251 }252 253 PRInt32 _MD_access(const char *name, PRAccessHow how)254 {255 PRInt32 rv, err;256 int amode;257 258 switch (how) {259 case PR_ACCESS_WRITE_OK:260 amode = W_OK;261 break;262 case PR_ACCESS_READ_OK:263 amode = R_OK;264 break;265 case PR_ACCESS_EXISTS:266 amode = F_OK;267 break;268 default:269 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);270 rv = -1;271 goto done;272 }273 rv = access(name, amode);274 275 if (rv < 0) {276 err = _MD_ERRNO();277 _PR_MD_MAP_ACCESS_ERROR(err);278 }279 280 done:281 return(rv);282 }283 284 PRInt32 _MD_mkdir(const char *name, PRIntn mode)285 {286 int rv, err;287 288 /*289 ** This lock is used to enforce rename semantics as described290 ** in PR_Rename. Look there for more fun details.291 */292 if (NULL !=_pr_rename_lock)293 PR_Lock(_pr_rename_lock);294 rv = mkdir(name, mode);295 if (rv < 0) {296 err = _MD_ERRNO();297 _PR_MD_MAP_MKDIR_ERROR(err);298 }299 if (NULL !=_pr_rename_lock)300 PR_Unlock(_pr_rename_lock);301 return rv;302 }303 304 PRInt32 _MD_rmdir(const char *name)305 {306 int rv, err;307 308 rv = rmdir(name);309 if (rv == -1) {310 err = _MD_ERRNO();311 _PR_MD_MAP_RMDIR_ERROR(err);312 }313 return rv;314 }315 316 PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)317 {318 PRThread *me = _PR_MD_CURRENT_THREAD();319 PRInt32 rv, err;320 #ifndef _PR_USE_POLL321 fd_set rd;322 #else323 struct pollfd pfd;324 #endif /* _PR_USE_POLL */325 PRInt32 osfd = fd->secret->md.osfd;326 327 #ifndef _PR_USE_POLL328 FD_ZERO(&rd);329 FD_SET(osfd, &rd);330 #else331 pfd.fd = osfd;332 pfd.events = POLLIN;333 #endif /* _PR_USE_POLL */334 while ((rv = read(osfd,buf,amount)) == -1) {335 err = _MD_ERRNO();336 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {337 if (fd->secret->nonblocking) {338 break;339 }340 if (!_PR_IS_NATIVE_THREAD(me)) {341 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ,342 PR_INTERVAL_NO_TIMEOUT)) < 0)343 goto done;344 } else {345 #ifndef _PR_USE_POLL346 while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))347 == -1 && (err = _MD_ERRNO()) == EINTR) {348 /* retry _MD_SELECT() if it is interrupted */349 }350 #else /* _PR_USE_POLL */351 while ((rv = _MD_POLL(&pfd, 1, -1))352 == -1 && (err = _MD_ERRNO()) == EINTR) {353 /* retry _MD_POLL() if it is interrupted */354 }355 #endif /* _PR_USE_POLL */356 if (rv == -1) {357 break;358 }359 }360 if (_PR_PENDING_INTERRUPT(me))361 break;362 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){363 continue;364 } else {365 break;366 }367 }368 if (rv < 0) {369 if (_PR_PENDING_INTERRUPT(me)) {370 me->flags &= ~_PR_INTERRUPT;371 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);372 } else {373 _PR_MD_MAP_READ_ERROR(err);374 }375 }376 done:377 return(rv);378 }379 380 PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)381 {382 PRThread *me = _PR_MD_CURRENT_THREAD();383 PRInt32 rv, err;384 #ifndef _PR_USE_POLL385 fd_set wd;386 #else387 struct pollfd pfd;388 #endif /* _PR_USE_POLL */389 PRInt32 osfd = fd->secret->md.osfd;390 391 #ifndef _PR_USE_POLL392 FD_ZERO(&wd);393 FD_SET(osfd, &wd);394 #else395 pfd.fd = osfd;396 pfd.events = POLLOUT;397 #endif /* _PR_USE_POLL */398 while ((rv = write(osfd,buf,amount)) == -1) {399 err = _MD_ERRNO();400 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {401 if (fd->secret->nonblocking) {402 break;403 }404 if (!_PR_IS_NATIVE_THREAD(me)) {405 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE,406 PR_INTERVAL_NO_TIMEOUT)) < 0)407 goto done;408 } else {409 #ifndef _PR_USE_POLL410 while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))411 == -1 && (err = _MD_ERRNO()) == EINTR) {412 /* retry _MD_SELECT() if it is interrupted */413 }414 #else /* _PR_USE_POLL */415 while ((rv = _MD_POLL(&pfd, 1, -1))416 == -1 && (err = _MD_ERRNO()) == EINTR) {417 /* retry _MD_POLL() if it is interrupted */418 }419 #endif /* _PR_USE_POLL */420 if (rv == -1) {421 break;422 }423 }424 if (_PR_PENDING_INTERRUPT(me))425 break;426 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){427 continue;428 } else {429 break;430 }431 }432 if (rv < 0) {433 if (_PR_PENDING_INTERRUPT(me)) {434 me->flags &= ~_PR_INTERRUPT;435 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);436 } else {437 _PR_MD_MAP_WRITE_ERROR(err);438 }439 }440 done:441 return(rv);442 }443 444 PRInt32 _MD_fsync(PRFileDesc *fd)445 {446 PRInt32 rv, err;447 448 rv = fsync(fd->secret->md.osfd);449 if (rv == -1) {450 err = _MD_ERRNO();451 _PR_MD_MAP_FSYNC_ERROR(err);452 }453 return(rv);454 }455 456 PRInt32 _MD_close(PRInt32 osfd)457 {458 PRInt32 rv, err;459 460 rv = close(osfd);461 if (rv == -1) {462 err = _MD_ERRNO();463 _PR_MD_MAP_CLOSE_ERROR(err);464 }465 return(rv);466 }467 468 PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)469 {470 PRInt32 osfd, err;471 472 osfd = socket(domain, type, proto);473 474 if (osfd == -1) {475 err = _MD_ERRNO();476 _PR_MD_MAP_SOCKET_ERROR(err);477 return(osfd);478 }479 480 return(osfd);481 }482 483 PRInt32 _MD_socketavailable(PRFileDesc *fd)484 {485 PRInt32 result;486 487 if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {488 _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());489 return -1;490 }491 return result;492 }493 494 PRInt64 _MD_socketavailable64(PRFileDesc *fd)495 {496 PRInt64 result;497 LL_I2L(result, _MD_socketavailable(fd));498 return result;499 } /* _MD_socketavailable64 */500 501 #define READ_FD 1502 #define WRITE_FD 2503 504 /*505 * socket_io_wait --506 *507 * wait for socket i/o, periodically checking for interrupt508 *509 * The first implementation uses select(), for platforms without510 * poll(). The second (preferred) implementation uses poll().511 */512 513 #ifndef _PR_USE_POLL514 515 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,516 PRIntervalTime timeout)517 {518 PRInt32 rv = -1;519 struct timeval tv;520 PRThread *me = _PR_MD_CURRENT_THREAD();521 PRIntervalTime epoch, now, elapsed, remaining;522 PRBool wait_for_remaining;523 PRInt32 syserror;524 fd_set rd_wr;525 526 switch (timeout) {527 case PR_INTERVAL_NO_WAIT:528 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);529 break;530 case PR_INTERVAL_NO_TIMEOUT:531 /*532 * This is a special case of the 'default' case below.533 * Please see the comments there.534 */535 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;536 tv.tv_usec = 0;537 FD_ZERO(&rd_wr);538 do {539 FD_SET(osfd, &rd_wr);540 if (fd_type == READ_FD)541 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);542 else543 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);544 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {545 _PR_MD_MAP_SELECT_ERROR(syserror);546 break;547 }548 if (_PR_PENDING_INTERRUPT(me)) {549 me->flags &= ~_PR_INTERRUPT;550 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);551 rv = -1;552 break;553 }554 } while (rv == 0 || (rv == -1 && syserror == EINTR));555 break;556 default:557 now = epoch = PR_IntervalNow();558 remaining = timeout;559 FD_ZERO(&rd_wr);560 do {561 /*562 * We block in _MD_SELECT for at most563 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,564 * so that there is an upper limit on the delay565 * before the interrupt bit is checked.566 */567 wait_for_remaining = PR_TRUE;568 tv.tv_sec = PR_IntervalToSeconds(remaining);569 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {570 wait_for_remaining = PR_FALSE;571 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;572 tv.tv_usec = 0;573 } else {574 tv.tv_usec = PR_IntervalToMicroseconds(575 remaining -576 PR_SecondsToInterval(tv.tv_sec));577 }578 FD_SET(osfd, &rd_wr);579 if (fd_type == READ_FD)580 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);581 else582 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);583 /*584 * we don't consider EINTR a real error585 */586 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {587 _PR_MD_MAP_SELECT_ERROR(syserror);588 break;589 }590 if (_PR_PENDING_INTERRUPT(me)) {591 me->flags &= ~_PR_INTERRUPT;592 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);593 rv = -1;594 break;595 }596 /*597 * We loop again if _MD_SELECT timed out or got interrupted598 * by a signal, and the timeout deadline has not passed yet.599 */600 if (rv == 0 || (rv == -1 && syserror == EINTR)) {601 /*602 * If _MD_SELECT timed out, we know how much time603 * we spent in blocking, so we can avoid a604 * PR_IntervalNow() call.605 */606 if (rv == 0) {607 if (wait_for_remaining) {608 now += remaining;609 } else {610 now += PR_SecondsToInterval(tv.tv_sec)611 + PR_MicrosecondsToInterval(tv.tv_usec);612 }613 } else {614 now = PR_IntervalNow();615 }616 elapsed = (PRIntervalTime) (now - epoch);617 if (elapsed >= timeout) {618 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);619 rv = -1;620 break;621 } else {622 remaining = timeout - elapsed;623 }624 }625 } while (rv == 0 || (rv == -1 && syserror == EINTR));626 break;627 }628 return(rv);629 }630 631 #else /* _PR_USE_POLL */632 633 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,634 PRIntervalTime timeout)635 {636 PRInt32 rv = -1;637 int msecs;638 PRThread *me = _PR_MD_CURRENT_THREAD();639 PRIntervalTime epoch, now, elapsed, remaining;640 PRBool wait_for_remaining;641 PRInt32 syserror;642 struct pollfd pfd;643 644 switch (timeout) {645 case PR_INTERVAL_NO_WAIT:646 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);647 break;648 case PR_INTERVAL_NO_TIMEOUT:649 /*650 * This is a special case of the 'default' case below.651 * Please see the comments there.652 */653 msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;654 pfd.fd = osfd;655 if (fd_type == READ_FD) {656 pfd.events = POLLIN;657 } else {658 pfd.events = POLLOUT;659 }660 do {661 rv = _MD_POLL(&pfd, 1, msecs);662 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {663 _PR_MD_MAP_POLL_ERROR(syserror);664 break;665 }666 /*667 * If POLLERR is set, don't process it; retry the operation668 */669 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {670 rv = -1;671 _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);672 break;673 }674 if (_PR_PENDING_INTERRUPT(me)) {675 me->flags &= ~_PR_INTERRUPT;676 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);677 rv = -1;678 break;679 }680 } while (rv == 0 || (rv == -1 && syserror == EINTR));681 break;682 default:683 now = epoch = PR_IntervalNow();684 remaining = timeout;685 pfd.fd = osfd;686 if (fd_type == READ_FD) {687 pfd.events = POLLIN;688 } else {689 pfd.events = POLLOUT;690 }691 do {692 /*693 * We block in _MD_POLL for at most694 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,695 * so that there is an upper limit on the delay696 * before the interrupt bit is checked.697 */698 wait_for_remaining = PR_TRUE;699 msecs = PR_IntervalToMilliseconds(remaining);700 if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {701 wait_for_remaining = PR_FALSE;702 msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;703 }704 rv = _MD_POLL(&pfd, 1, msecs);705 /*706 * we don't consider EINTR a real error707 */708 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {709 _PR_MD_MAP_POLL_ERROR(syserror);710 break;711 }712 if (_PR_PENDING_INTERRUPT(me)) {713 me->flags &= ~_PR_INTERRUPT;714 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);715 rv = -1;716 break;717 }718 /*719 * If POLLERR is set, don't process it; retry the operation720 */721 if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {722 rv = -1;723 _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);724 break;725 }726 /*727 * We loop again if _MD_POLL timed out or got interrupted728 * by a signal, and the timeout deadline has not passed yet.729 */730 if (rv == 0 || (rv == -1 && syserror == EINTR)) {731 /*732 * If _MD_POLL timed out, we know how much time733 * we spent in blocking, so we can avoid a734 * PR_IntervalNow() call.735 */736 if (rv == 0) {737 if (wait_for_remaining) {738 now += remaining;739 } else {740 now += PR_MillisecondsToInterval(msecs);741 }742 } else {743 now = PR_IntervalNow();744 }745 elapsed = (PRIntervalTime) (now - epoch);746 if (elapsed >= timeout) {747 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);748 rv = -1;749 break;750 } else {751 remaining = timeout - elapsed;752 }753 }754 } while (rv == 0 || (rv == -1 && syserror == EINTR));755 break;756 }757 return(rv);758 }759 760 #endif /* _PR_USE_POLL */761 762 static PRInt32 local_io_wait(763 PRInt32 osfd,764 PRInt32 wait_flag,765 PRIntervalTime timeout)766 {767 _PRUnixPollDesc pd;768 PRInt32 rv;769 770 PR_LOG(_pr_io_lm, PR_LOG_MIN,771 ("waiting to %s on osfd=%d",772 (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write",773 osfd));774 775 if (timeout == PR_INTERVAL_NO_WAIT) return 0;776 777 pd.osfd = osfd;778 pd.in_flags = wait_flag;779 pd.out_flags = 0;780 781 rv = _PR_WaitForMultipleFDs(&pd, 1, timeout);782 783 if (rv == 0) {784 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);785 rv = -1;786 }787 return rv;788 }789 790 791 PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,792 PRInt32 flags, PRIntervalTime timeout)793 {794 PRInt32 osfd = fd->secret->md.osfd;795 PRInt32 rv, err;796 PRThread *me = _PR_MD_CURRENT_THREAD();797 798 /*799 * Many OS's (Solaris, Unixware) have a broken recv which won't read800 * from socketpairs. As long as we don't use flags on socketpairs, this801 * is a decent fix. - mikep802 */803 #if defined(UNIXWARE) || defined(SOLARIS) || defined(NCR)804 while ((rv = read(osfd,buf,amount)) == -1) {805 #else806 while ((rv = recv(osfd,buf,amount,flags)) == -1) {807 #endif808 err = _MD_ERRNO();809 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {810 if (fd->secret->nonblocking) {811 break;812 }813 if (!_PR_IS_NATIVE_THREAD(me)) {814 if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0)815 goto done;816 } else {817 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)818 goto done;819 }820 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){821 continue;822 } else {823 break;824 }825 }826 if (rv < 0) {827 _PR_MD_MAP_RECV_ERROR(err);828 }829 done:830 return(rv);831 }832 833 PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,834 PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,835 PRIntervalTime timeout)836 {837 PRInt32 osfd = fd->secret->md.osfd;838 PRInt32 rv, err;839 PRThread *me = _PR_MD_CURRENT_THREAD();840 841 while ((*addrlen = PR_NETADDR_SIZE(addr)),842 ((rv = recvfrom(osfd, buf, amount, flags,843 (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {844 err = _MD_ERRNO();845 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {846 if (fd->secret->nonblocking) {847 break;848 }849 if (!_PR_IS_NATIVE_THREAD(me)) {850 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)851 goto done;852 } else {853 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)854 goto done;855 }856 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){857 continue;858 } else {859 break;860 }861 }862 if (rv < 0) {863 _PR_MD_MAP_RECVFROM_ERROR(err);864 }865 done:866 #ifdef _PR_HAVE_SOCKADDR_LEN867 if (rv != -1) {868 /* ignore the sa_len field of struct sockaddr */869 if (addr) {870 addr->raw.family = ((struct sockaddr *) addr)->sa_family;871 }872 }873 #endif /* _PR_HAVE_SOCKADDR_LEN */874 return(rv);875 }876 877 PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,878 PRInt32 flags, PRIntervalTime timeout)879 {880 PRInt32 osfd = fd->secret->md.osfd;881 PRInt32 rv, err;882 PRThread *me = _PR_MD_CURRENT_THREAD();883 #if defined(SOLARIS)884 PRInt32 tmp_amount = amount;885 #endif886 887 /*888 * On pre-2.6 Solaris, send() is much slower than write().889 * On 2.6 and beyond, with in-kernel sockets, send() and890 * write() are fairly equivalent in performance.891 */892 #if defined(SOLARIS)893 PR_ASSERT(0 == flags);894 while ((rv = write(osfd,buf,tmp_amount)) == -1) {895 #else896 while ((rv = send(osfd,buf,amount,flags)) == -1) {897 #endif898 err = _MD_ERRNO();899 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {900 if (fd->secret->nonblocking) {901 break;902 }903 if (!_PR_IS_NATIVE_THREAD(me)) {904 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)905 goto done;906 } else {907 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)908 goto done;909 }910 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){911 continue;912 } else {913 #if defined(SOLARIS)914 /*915 * The write system call has been reported to return the ERANGE916 * error on occasion. Try to write in smaller chunks to workaround917 * this bug.918 */919 if (err == ERANGE) {920 if (tmp_amount > 1) {921 tmp_amount = tmp_amount/2; /* half the bytes */922 continue;923 }924 }925 #endif926 break;927 }928 }929 /*930 * optimization; if bytes sent is less than "amount" call931 * select before returning. This is because it is likely that932 * the next send() call will return EWOULDBLOCK.933 */934 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)935 && (timeout != PR_INTERVAL_NO_WAIT)) {936 if (_PR_IS_NATIVE_THREAD(me)) {937 if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {938 rv = -1;939 goto done;940 }941 } else {942 if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {943 rv = -1;944 goto done;945 }946 }947 }948 if (rv < 0) {949 _PR_MD_MAP_SEND_ERROR(err);950 }951 done:952 return(rv);953 }954 955 PRInt32 _MD_sendto(956 PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,957 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)958 {959 PRInt32 osfd = fd->secret->md.osfd;960 PRInt32 rv, err;961 PRThread *me = _PR_MD_CURRENT_THREAD();962 #ifdef _PR_HAVE_SOCKADDR_LEN963 PRNetAddr addrCopy;964 965 addrCopy = *addr;966 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;967 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;968 969 while ((rv = sendto(osfd, buf, amount, flags,970 (struct sockaddr *) &addrCopy, addrlen)) == -1) {971 #else972 while ((rv = sendto(osfd, buf, amount, flags,973 (struct sockaddr *) addr, addrlen)) == -1) {974 #endif975 err = _MD_ERRNO();976 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {977 if (fd->secret->nonblocking) {978 break;979 }980 if (!_PR_IS_NATIVE_THREAD(me)) {981 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)982 goto done;983 } else {984 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)985 goto done;986 }987 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){988 continue;989 } else {990 break;991 }992 }993 if (rv < 0) {994 _PR_MD_MAP_SENDTO_ERROR(err);995 }996 done:997 return(rv);998 }999 1000 PRInt32 _MD_writev(1001 PRFileDesc *fd, const PRIOVec *iov,1002 PRInt32 iov_size, PRIntervalTime timeout)1003 {1004 PRInt32 rv, err;1005 PRThread *me = _PR_MD_CURRENT_THREAD();1006 PRInt32 index, amount = 0;1007 PRInt32 osfd = fd->secret->md.osfd;1008 1009 /*1010 * Calculate the total number of bytes to be sent; needed for1011 * optimization later.1012 * We could avoid this if this number was passed in; but it is1013 * probably not a big deal because iov_size is usually small (less than1014 * 3)1015 */1016 if (!fd->secret->nonblocking) {1017 for (index=0; index<iov_size; index++) {1018 amount += iov[index].iov_len;1019 }1020 }1021 1022 while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {1023 err = _MD_ERRNO();1024 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {1025 if (fd->secret->nonblocking) {1026 break;1027 }1028 if (!_PR_IS_NATIVE_THREAD(me)) {1029 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)1030 goto done;1031 } else {1032 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)1033 goto done;1034 }1035 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){1036 continue;1037 } else {1038 break;1039 }1040 }1041 /*1042 * optimization; if bytes sent is less than "amount" call1043 * select before returning. This is because it is likely that1044 * the next writev() call will return EWOULDBLOCK.1045 */1046 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)1047 && (timeout != PR_INTERVAL_NO_WAIT)) {1048 if (_PR_IS_NATIVE_THREAD(me)) {1049 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {1050 rv = -1;1051 goto done;1052 }1053 } else {1054 if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {1055 rv = -1;1056 goto done;1057 }1058 }1059 }1060 if (rv < 0) {1061 _PR_MD_MAP_WRITEV_ERROR(err);1062 }1063 done:1064 return(rv);1065 }1066 1067 PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr,1068 PRUint32 *addrlen, PRIntervalTime timeout)1069 {1070 PRInt32 osfd = fd->secret->md.osfd;1071 PRInt32 rv, err;1072 PRThread *me = _PR_MD_CURRENT_THREAD();1073 1074 while ((rv = accept(osfd, (struct sockaddr *) addr,1075 (_PRSockLen_t *)addrlen)) == -1) {1076 err = _MD_ERRNO();1077 if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) {1078 if (fd->secret->nonblocking) {1079 break;1080 }1081 if (!_PR_IS_NATIVE_THREAD(me)) {1082 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)1083 goto done;1084 } else {1085 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)1086 goto done;1087 }1088 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){1089 continue;1090 } else {1091 break;1092 }1093 }1094 if (rv < 0) {1095 _PR_MD_MAP_ACCEPT_ERROR(err);1096 }1097 done:1098 #ifdef _PR_HAVE_SOCKADDR_LEN1099 if (rv != -1) {1100 /* ignore the sa_len field of struct sockaddr */1101 if (addr) {1102 addr->raw.family = ((struct sockaddr *) addr)->sa_family;1103 }1104 }1105 #endif /* _PR_HAVE_SOCKADDR_LEN */1106 return(rv);1107 }1108 1109 extern int _connect (int s, const struct sockaddr *name, int namelen);1110 PRInt32 _MD_connect(1111 PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)1112 {1113 PRInt32 rv, err;1114 PRThread *me = _PR_MD_CURRENT_THREAD();1115 PRInt32 osfd = fd->secret->md.osfd;1116 #ifdef IRIX1117 extern PRInt32 _MD_irix_connect(1118 PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);1119 #endif1120 #ifdef _PR_HAVE_SOCKADDR_LEN1121 PRNetAddr addrCopy;1122 1123 addrCopy = *addr;1124 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;1125 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;1126 #endif1127 1128 /*1129 * We initiate the connection setup by making a nonblocking connect()1130 * call. If the connect() call fails, there are two cases we handle1131 * specially:1132 * 1. The connect() call was interrupted by a signal. In this case1133 * we simply retry connect().1134 * 2. The NSPR socket is nonblocking and connect() fails with1135 * EINPROGRESS. We first wait until the socket becomes writable.1136 * Then we try to find out whether the connection setup succeeded1137 * or failed.1138 */1139 1140 retry:1141 #ifdef IRIX1142 if ((rv = _MD_irix_connect(osfd, addr, addrlen, timeout)) == -1) {1143 #else1144 #ifdef _PR_HAVE_SOCKADDR_LEN1145 if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {1146 #else1147 if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {1148 #endif1149 #endif1150 err = _MD_ERRNO();1151 1152 if (err == EINTR) {1153 if (_PR_PENDING_INTERRUPT(me)) {1154 me->flags &= ~_PR_INTERRUPT;1155 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);1156 return -1;1157 }1158 goto retry;1159 }1160 1161 if (!fd->secret->nonblocking && (err == EINPROGRESS)) {1162 if (!_PR_IS_NATIVE_THREAD(me)) {1163 1164 if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)1165 return -1;1166 } else {1167 /*1168 * socket_io_wait() may return -1 or 1.1169 */1170 1171 rv = socket_io_wait(osfd, WRITE_FD, timeout);1172 if (rv == -1) {1173 return -1;1174 }1175 }1176 1177 PR_ASSERT(rv == 1);1178 if (_PR_PENDING_INTERRUPT(me)) {1179 me->flags &= ~_PR_INTERRUPT;1180 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);1181 return -1;1182 }1183 err = _MD_unix_get_nonblocking_connect_error(osfd);1184 if (err != 0) {1185 _PR_MD_MAP_CONNECT_ERROR(err);1186 return -1;1187 }1188 return 0;1189 }1190 1191 _PR_MD_MAP_CONNECT_ERROR(err);1192 }1193 1194 return rv;1195 } /* _MD_connect */1196 1197 PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)1198 {1199 PRInt32 rv, err;1200 #ifdef _PR_HAVE_SOCKADDR_LEN1201 PRNetAddr addrCopy;1202 1203 addrCopy = *addr;1204 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;1205 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;1206 rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);1207 #else1208 rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);1209 #endif1210 if (rv < 0) {1211 err = _MD_ERRNO();1212 _PR_MD_MAP_BIND_ERROR(err);1213 }1214 return(rv);1215 }1216 1217 PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)1218 {1219 PRInt32 rv, err;1220 1221 rv = listen(fd->secret->md.osfd, backlog);1222 if (rv < 0) {1223 err = _MD_ERRNO();1224 _PR_MD_MAP_LISTEN_ERROR(err);1225 }1226 return(rv);1227 }1228 1229 PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how)1230 {1231 PRInt32 rv, err;1232 1233 rv = shutdown(fd->secret->md.osfd, how);1234 if (rv < 0) {1235 err = _MD_ERRNO();1236 _PR_MD_MAP_SHUTDOWN_ERROR(err);1237 }1238 return(rv);1239 }1240 1241 PRInt32 _MD_socketpair(int af, int type, int flags,1242 PRInt32 *osfd)1243 {1244 PRInt32 rv, err;1245 1246 rv = socketpair(af, type, flags, osfd);1247 if (rv < 0) {1248 err = _MD_ERRNO();1249 _PR_MD_MAP_SOCKETPAIR_ERROR(err);1250 }1251 return rv;1252 }1253 1254 PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,1255 PRUint32 *addrlen)1256 {1257 PRInt32 rv, err;1258 1259 rv = getsockname(fd->secret->md.osfd,1260 (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);1261 #ifdef _PR_HAVE_SOCKADDR_LEN1262 if (rv == 0) {1263 /* ignore the sa_len field of struct sockaddr */1264 if (addr) {1265 addr->raw.family = ((struct sockaddr *) addr)->sa_family;1266 }1267 }1268 #endif /* _PR_HAVE_SOCKADDR_LEN */1269 if (rv < 0) {1270 err = _MD_ERRNO();1271 _PR_MD_MAP_GETSOCKNAME_ERROR(err);1272 }1273 return rv==0?PR_SUCCESS:PR_FAILURE;1274 }1275 1276 PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,1277 PRUint32 *addrlen)1278 {1279 PRInt32 rv, err;1280 1281 rv = getpeername(fd->secret->md.osfd,1282 (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);1283 #ifdef _PR_HAVE_SOCKADDR_LEN1284 if (rv == 0) {1285 /* ignore the sa_len field of struct sockaddr */1286 if (addr) {1287 addr->raw.family = ((struct sockaddr *) addr)->sa_family;1288 }1289 }1290 #endif /* _PR_HAVE_SOCKADDR_LEN */1291 if (rv < 0) {1292 err = _MD_ERRNO();1293 _PR_MD_MAP_GETPEERNAME_ERROR(err);1294 }1295 return rv==0?PR_SUCCESS:PR_FAILURE;1296 }1297 1298 PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,1299 PRInt32 optname, char* optval, PRInt32* optlen)1300 {1301 PRInt32 rv, err;1302 1303 rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);1304 if (rv < 0) {1305 err = _MD_ERRNO();1306 _PR_MD_MAP_GETSOCKOPT_ERROR(err);1307 }1308 return rv==0?PR_SUCCESS:PR_FAILURE;1309 }1310 1311 PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,1312 PRInt32 optname, const char* optval, PRInt32 optlen)1313 {1314 PRInt32 rv, err;1315 1316 rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);1317 if (rv < 0) {1318 err = _MD_ERRNO();1319 _PR_MD_MAP_SETSOCKOPT_ERROR(err);1320 }1321 return rv==0?PR_SUCCESS:PR_FAILURE;1322 }1323 1324 PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable)1325 {1326 int rv;1327 1328 rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);1329 if (-1 == rv) {1330 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());1331 return PR_FAILURE;1332 }1333 return PR_SUCCESS;1334 }1335 1336 void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported)1337 {1338 if (imported) {1339 fd->secret->inheritable = _PR_TRI_UNKNOWN;1340 } else {1341 /* By default, a Unix fd is not closed on exec. */1342 #ifdef DEBUG1343 {1344 int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);1345 PR_ASSERT(0 == flags);1346 }1347 #endif1348 fd->secret->inheritable = _PR_TRI_TRUE;1349 }1350 }1351 1352 /************************************************************************/1353 #if !defined(_PR_USE_POLL)1354 1355 /*1356 ** Scan through io queue and find any bad fd's that triggered the error1357 ** from _MD_SELECT1358 */1359 static void FindBadFDs(void)1360 {1361 PRCList *q;1362 PRThread *me = _MD_CURRENT_THREAD();1363 1364 PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));1365 q = (_PR_IOQ(me->cpu)).next;1366 _PR_IOQ_MAX_OSFD(me->cpu) = -1;1367 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;1368 while (q != &_PR_IOQ(me->cpu)) {1369 PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);1370 PRBool notify = PR_FALSE;1371 _PRUnixPollDesc *pds = pq->pds;1372 _PRUnixPollDesc *epds = pds + pq->npds;1373 PRInt32 pq_max_osfd = -1;1374 1375 q = q->next;1376 for (; pds < epds; pds++) {1377 PRInt32 osfd = pds->osfd;1378 pds->out_flags = 0;1379 PR_ASSERT(osfd >= 0 || pds->in_flags == 0);1380 if (pds->in_flags == 0) {1381 continue; /* skip this fd */1382 }1383 if (fcntl(osfd, F_GETFL, 0) == -1) {1384 /* Found a bad descriptor, remove it from the fd_sets. */1385 PR_LOG(_pr_io_lm, PR_LOG_MAX,1386 ("file descriptor %d is bad", osfd));1387 pds->out_flags = _PR_UNIX_POLL_NVAL;1388 notify = PR_TRUE;1389 }1390 if (osfd > pq_max_osfd) {1391 pq_max_osfd = osfd;1392 }1393 }1394 1395 if (notify) {1396 PRIntn pri;1397 PR_REMOVE_LINK(&pq->links);1398 pq->on_ioq = PR_FALSE;1399 1400 /*1401 * Decrement the count of descriptors for each desciptor/event1402 * because this I/O request is being removed from the1403 * ioq1404 */1405 pds = pq->pds;1406 for (; pds < epds; pds++) {1407 PRInt32 osfd = pds->osfd;1408 PRInt16 in_flags = pds->in_flags;1409 PR_ASSERT(osfd >= 0 || in_flags == 0);1410 if (in_flags & _PR_UNIX_POLL_READ) {1411 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)1412 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));1413 }1414 if (in_flags & _PR_UNIX_POLL_WRITE) {1415 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)1416 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));1417 }1418 if (in_flags & _PR_UNIX_POLL_EXCEPT) {1419 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)1420 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));1421 }1422 }1423 1424 _PR_THREAD_LOCK(pq->thr);1425 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {1426 _PRCPU *cpu = pq->thr->cpu;1427 _PR_SLEEPQ_LOCK(pq->thr->cpu);1428 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);1429 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);1430 1431 if (pq->thr->flags & _PR_SUSPENDING) {1432 /*1433 * set thread state to SUSPENDED;1434 * a Resume operation on the thread1435 * will move it to the runQ1436 */1437 pq->thr->state = _PR_SUSPENDED;1438 _PR_MISCQ_LOCK(pq->thr->cpu);1439 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);1440 _PR_MISCQ_UNLOCK(pq->thr->cpu);1441 } else {1442 pri = pq->thr->priority;1443 pq->thr->state = _PR_RUNNABLE;1444 1445 _PR_RUNQ_LOCK(cpu);1446 _PR_ADD_RUNQ(pq->thr, cpu, pri);1447 _PR_RUNQ_UNLOCK(cpu);1448 }1449 }1450 _PR_THREAD_UNLOCK(pq->thr);1451 } else {1452 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))1453 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;1454 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)1455 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;1456 }1457 }1458 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1459 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])1460 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];1461 }1462 }1463 #endif /* !defined(_PR_USE_POLL) */1464 1465 /************************************************************************/1466 1467 /*1468 ** Called by the scheduler when there is nothing to do. This means that1469 ** all threads are blocked on some monitor somewhere.1470 **1471 ** Note: this code doesn't release the scheduler lock.1472 */1473 /*1474 ** Pause the current CPU. longjmp to the cpu's pause stack1475 **1476 ** This must be called with the scheduler locked1477 */1478 void _MD_PauseCPU(PRIntervalTime ticks)1479 {1480 PRThread *me = _MD_CURRENT_THREAD();1481 #ifdef _PR_USE_POLL1482 int timeout;1483 struct pollfd *pollfds; /* an array of pollfd structures */1484 struct pollfd *pollfdPtr; /* a pointer that steps through the array */1485 unsigned long npollfds; /* number of pollfd structures in array */1486 unsigned long pollfds_size;1487 int nfd; /* to hold the return value of poll() */1488 #else1489 struct timeval timeout, *tvp;1490 fd_set r, w, e;1491 fd_set *rp, *wp, *ep;1492 PRInt32 max_osfd, nfd;1493 #endif /* _PR_USE_POLL */1494 PRInt32 rv;1495 PRCList *q;1496 PRUint32 min_timeout;1497 sigset_t oldset;1498 #ifdef IRIX1499 extern sigset_t ints_off;1500 #endif1501 1502 PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);1503 1504 _PR_MD_IOQ_LOCK();1505 1506 #ifdef _PR_USE_POLL1507 /* Build up the pollfd structure array to wait on */1508 1509 /* Find out how many pollfd structures are needed */1510 npollfds = _PR_IOQ_OSFD_CNT(me->cpu);1511 PR_ASSERT(npollfds >= 0);1512 1513 /*1514 * We use a pipe to wake up a native thread. An fd is needed1515 * for the pipe and we poll it for reading.1516 */1517 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1518 npollfds++;1519 #ifdef IRIX1520 /*1521 * On Irix, a second pipe is used to cause the primordial cpu to1522 * wakeup and exit, when the process is exiting because of a call1523 * to exit/PR_ProcessExit.1524 */1525 if (me->cpu->id == 0) {1526 npollfds++;1527 }1528 #endif1529 }1530 1531 /*1532 * if the cpu's pollfd array is not big enough, release it and allocate a new one1533 */1534 if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {1535 if (_PR_IOQ_POLLFDS(me->cpu) != NULL)1536 PR_DELETE(_PR_IOQ_POLLFDS(me->cpu));1537 pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);1538 pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));1539 _PR_IOQ_POLLFDS(me->cpu) = pollfds;1540 _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;1541 } else {1542 pollfds = _PR_IOQ_POLLFDS(me->cpu);1543 }1544 pollfdPtr = pollfds;1545 1546 /*1547 * If we need to poll the pipe for waking up a native thread,1548 * the pipe's fd is the first element in the pollfds array.1549 */1550 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1551 pollfdPtr->fd = _pr_md_pipefd[0];1552 pollfdPtr->events = POLLIN;1553 pollfdPtr++;1554 #ifdef IRIX1555 /*1556 * On Irix, the second element is the exit pipe1557 */1558 if (me->cpu->id == 0) {1559 pollfdPtr->fd = _pr_irix_primoridal_cpu_fd[0];1560 pollfdPtr->events = POLLIN;1561 pollfdPtr++;1562 }1563 #endif1564 }1565 1566 min_timeout = PR_INTERVAL_NO_TIMEOUT;1567 for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {1568 PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);1569 _PRUnixPollDesc *pds = pq->pds;1570 _PRUnixPollDesc *epds = pds + pq->npds;1571 1572 if (pq->timeout < min_timeout) {1573 min_timeout = pq->timeout;1574 }1575 for (; pds < epds; pds++, pollfdPtr++) {1576 /*1577 * Assert that the pollfdPtr pointer does not go1578 * beyond the end of the pollfds array1579 */1580 PR_ASSERT(pollfdPtr < pollfds + npollfds);1581 pollfdPtr->fd = pds->osfd;1582 /* direct copy of poll flags */1583 pollfdPtr->events = pds->in_flags;1584 }1585 }1586 _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;1587 #else1588 /*1589 * assigment of fd_sets1590 */1591 r = _PR_FD_READ_SET(me->cpu);1592 w = _PR_FD_WRITE_SET(me->cpu);1593 e = _PR_FD_EXCEPTION_SET(me->cpu);1594 1595 rp = &r;1596 wp = &w;1597 ep = &e;1598 1599 max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;1600 min_timeout = _PR_IOQ_TIMEOUT(me->cpu);1601 #endif /* _PR_USE_POLL */1602 /*1603 ** Compute the minimum timeout value: make it the smaller of the1604 ** timeouts specified by the i/o pollers or the timeout of the first1605 ** sleeping thread.1606 */1607 q = _PR_SLEEPQ(me->cpu).next;1608 1609 if (q != &_PR_SLEEPQ(me->cpu)) {1610 PRThread *t = _PR_THREAD_PTR(q);1611 1612 if (t->sleep < min_timeout) {1613 min_timeout = t->sleep;1614 }1615 }1616 if (min_timeout > ticks) {1617 min_timeout = ticks;1618 }1619 1620 #ifdef _PR_USE_POLL1621 if (min_timeout == PR_INTERVAL_NO_TIMEOUT)1622 timeout = -1;1623 else1624 timeout = PR_IntervalToMilliseconds(min_timeout);1625 #else1626 if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {1627 tvp = NULL;1628 } else {1629 timeout.tv_sec = PR_IntervalToSeconds(min_timeout);1630 timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)1631 % PR_USEC_PER_SEC;1632 tvp = &timeout;1633 }1634 #endif /* _PR_USE_POLL */1635 1636 _PR_MD_IOQ_UNLOCK();1637 _MD_CHECK_FOR_EXIT();1638 /*1639 * check for i/o operations1640 */1641 #ifndef _PR_NO_CLOCK_TIMER1642 /*1643 * Disable the clock interrupts while we are in select, if clock interrupts1644 * are enabled. Otherwise, when the select/poll calls are interrupted, the1645 * timer value starts ticking from zero again when the system call is restarted.1646 */1647 #ifdef IRIX1648 /*1649 * SIGCHLD signal is used on Irix to detect he termination of an1650 * sproc by SIGSEGV, SIGBUS or SIGABRT signals when1651 * _nspr_terminate_on_error is set.1652 */1653 if ((!_nspr_noclock) || (_nspr_terminate_on_error))1654 #else1655 if (!_nspr_noclock)1656 #endif /* IRIX */1657 #ifdef IRIX1658 sigprocmask(SIG_BLOCK, &ints_off, &oldset);1659 #else1660 PR_ASSERT(sigismember(&timer_set, SIGALRM));1661 sigprocmask(SIG_BLOCK, &timer_set, &oldset);1662 #endif /* IRIX */1663 #endif /* !_PR_NO_CLOCK_TIMER */1664 1665 #ifndef _PR_USE_POLL1666 PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));1667 nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);1668 #else1669 nfd = _MD_POLL(pollfds, npollfds, timeout);1670 #endif /* !_PR_USE_POLL */1671 1672 #ifndef _PR_NO_CLOCK_TIMER1673 #ifdef IRIX1674 if ((!_nspr_noclock) || (_nspr_terminate_on_error))1675 #else1676 if (!_nspr_noclock)1677 #endif /* IRIX */1678 sigprocmask(SIG_SETMASK, &oldset, 0);1679 #endif /* !_PR_NO_CLOCK_TIMER */1680 1681 _MD_CHECK_FOR_EXIT();1682 1683 #ifdef IRIX1684 _PR_MD_primordial_cpu();1685 #endif1686 1687 _PR_MD_IOQ_LOCK();1688 /*1689 ** Notify monitors that are associated with the selected descriptors.1690 */1691 #ifdef _PR_USE_POLL1692 if (nfd > 0) {1693 pollfdPtr = pollfds;1694 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1695 /*1696 * Assert that the pipe is the first element in the1697 * pollfds array.1698 */1699 PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);1700 if ((pollfds[0].revents & POLLIN) && (nfd == 1)) {1701 /*1702 * woken up by another thread; read all the data1703 * in the pipe to empty the pipe1704 */1705 while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,1706 PIPE_BUF)) == PIPE_BUF){1707 }1708 PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));1709 }1710 pollfdPtr++;1711 #ifdef IRIX1712 /*1713 * On Irix, check to see if the primordial cpu needs to exit1714 * to cause the process to terminate1715 */1716 if (me->cpu->id == 0) {1717 PR_ASSERT(pollfds[1].fd == _pr_irix_primoridal_cpu_fd[0]);1718 if (pollfdPtr->revents & POLLIN) {1719 if (_pr_irix_process_exit) {1720 /*1721 * process exit due to a call to PR_ProcessExit1722 */1723 prctl(PR_SETEXITSIG, SIGKILL);1724 _exit(_pr_irix_process_exit_code);1725 } else {1726 while ((rv = read(_pr_irix_primoridal_cpu_fd[0],1727 _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {1728 }1729 PR_ASSERT(rv > 0);1730 }1731 }1732 pollfdPtr++;1733 }1734 #endif1735 }1736 for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {1737 PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);1738 PRBool notify = PR_FALSE;1739 _PRUnixPollDesc *pds = pq->pds;1740 _PRUnixPollDesc *epds = pds + pq->npds;1741 1742 for (; pds < epds; pds++, pollfdPtr++) {1743 /*1744 * Assert that the pollfdPtr pointer does not go beyond1745 * the end of the pollfds array.1746 */1747 PR_ASSERT(pollfdPtr < pollfds + npollfds);1748 /*1749 * Assert that the fd's in the pollfds array (stepped1750 * through by pollfdPtr) are in the same order as1751 * the fd's in _PR_IOQ() (stepped through by q and pds).1752 * This is how the pollfds array was created earlier.1753 */1754 PR_ASSERT(pollfdPtr->fd == pds->osfd);1755 pds->out_flags = pollfdPtr->revents;1756 /* Negative fd's are ignored by poll() */1757 if (pds->osfd >= 0 && pds->out_flags) {1758 notify = PR_TRUE;1759 }1760 }1761 if (notify) {1762 PRIntn pri;1763 PRThread *thred;1764 1765 PR_REMOVE_LINK(&pq->links);1766 pq->on_ioq = PR_FALSE;1767 1768 thred = pq->thr;1769 _PR_THREAD_LOCK(thred);1770 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {1771 _PRCPU *cpu = pq->thr->cpu;1772 _PR_SLEEPQ_LOCK(pq->thr->cpu);1773 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);1774 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);1775 1776 if (pq->thr->flags & _PR_SUSPENDING) {1777 /*1778 * set thread state to SUSPENDED;1779 * a Resume operation on the thread1780 * will move it to the runQ1781 */1782 pq->thr->state = _PR_SUSPENDED;1783 _PR_MISCQ_LOCK(pq->thr->cpu);1784 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);1785 _PR_MISCQ_UNLOCK(pq->thr->cpu);1786 } else {1787 pri = pq->thr->priority;1788 pq->thr->state = _PR_RUNNABLE;1789 1790 _PR_RUNQ_LOCK(cpu);1791 _PR_ADD_RUNQ(pq->thr, cpu, pri);1792 _PR_RUNQ_UNLOCK(cpu);1793 if (_pr_md_idle_cpus > 1)1794 _PR_MD_WAKEUP_WAITER(thred);1795 }1796 }1797 _PR_THREAD_UNLOCK(thred);1798 _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;1799 PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);1800 }1801 }1802 } else if (nfd == -1) {1803 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));1804 }1805 1806 #else1807 if (nfd > 0) {1808 q = _PR_IOQ(me->cpu).next;1809 _PR_IOQ_MAX_OSFD(me->cpu) = -1;1810 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;1811 while (q != &_PR_IOQ(me->cpu)) {1812 PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);1813 PRBool notify = PR_FALSE;1814 _PRUnixPollDesc *pds = pq->pds;1815 _PRUnixPollDesc *epds = pds + pq->npds;1816 PRInt32 pq_max_osfd = -1;1817 1818 q = q->next;1819 for (; pds < epds; pds++) {1820 PRInt32 osfd = pds->osfd;1821 PRInt16 in_flags = pds->in_flags;1822 PRInt16 out_flags = 0;1823 PR_ASSERT(osfd >= 0 || in_flags == 0);1824 if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) {1825 out_flags |= _PR_UNIX_POLL_READ;1826 }1827 if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) {1828 out_flags |= _PR_UNIX_POLL_WRITE;1829 }1830 if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {1831 out_flags |= _PR_UNIX_POLL_EXCEPT;1832 }1833 pds->out_flags = out_flags;1834 if (out_flags) {1835 notify = PR_TRUE;1836 }1837 if (osfd > pq_max_osfd) {1838 pq_max_osfd = osfd;1839 }1840 }1841 if (notify == PR_TRUE) {1842 PRIntn pri;1843 PRThread *thred;1844 1845 PR_REMOVE_LINK(&pq->links);1846 pq->on_ioq = PR_FALSE;1847 1848 /*1849 * Decrement the count of descriptors for each desciptor/event1850 * because this I/O request is being removed from the1851 * ioq1852 */1853 pds = pq->pds;1854 for (; pds < epds; pds++) {1855 PRInt32 osfd = pds->osfd;1856 PRInt16 in_flags = pds->in_flags;1857 PR_ASSERT(osfd >= 0 || in_flags == 0);1858 if (in_flags & _PR_UNIX_POLL_READ) {1859 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)1860 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));1861 }1862 if (in_flags & _PR_UNIX_POLL_WRITE) {1863 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)1864 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));1865 }1866 if (in_flags & _PR_UNIX_POLL_EXCEPT) {1867 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)1868 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));1869 }1870 }1871 1872 /*1873 * Because this thread can run on a different cpu right1874 * after being added to the run queue, do not dereference1875 * pq1876 */1877 thred = pq->thr;1878 _PR_THREAD_LOCK(thred);1879 if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {1880 _PRCPU *cpu = thred->cpu;1881 _PR_SLEEPQ_LOCK(pq->thr->cpu);1882 _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);1883 _PR_SLEEPQ_UNLOCK(pq->thr->cpu);1884 1885 if (pq->thr->flags & _PR_SUSPENDING) {1886 /*1887 * set thread state to SUSPENDED;1888 * a Resume operation on the thread1889 * will move it to the runQ1890 */1891 pq->thr->state = _PR_SUSPENDED;1892 _PR_MISCQ_LOCK(pq->thr->cpu);1893 _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);1894 _PR_MISCQ_UNLOCK(pq->thr->cpu);1895 } else {1896 pri = pq->thr->priority;1897 pq->thr->state = _PR_RUNNABLE;1898 1899 pq->thr->cpu = cpu;1900 _PR_RUNQ_LOCK(cpu);1901 _PR_ADD_RUNQ(pq->thr, cpu, pri);1902 _PR_RUNQ_UNLOCK(cpu);1903 if (_pr_md_idle_cpus > 1)1904 _PR_MD_WAKEUP_WAITER(thred);1905 }1906 }1907 _PR_THREAD_UNLOCK(thred);1908 } else {1909 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))1910 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;1911 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)1912 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;1913 }1914 }1915 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1916 if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {1917 /*1918 * woken up by another thread; read all the data1919 * in the pipe to empty the pipe1920 */1921 while ((rv =1922 read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))1923 == PIPE_BUF){1924 }1925 PR_ASSERT((rv > 0) ||1926 ((rv == -1) && (errno == EAGAIN)));1927 }1928 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])1929 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];1930 #ifdef IRIX1931 if ((me->cpu->id == 0) &&1932 (FD_ISSET(_pr_irix_primoridal_cpu_fd[0], rp))) {1933 if (_pr_irix_process_exit) {1934 /*1935 * process exit due to a call to PR_ProcessExit1936 */1937 prctl(PR_SETEXITSIG, SIGKILL);1938 _exit(_pr_irix_process_exit_code);1939 } else {1940 while ((rv = read(_pr_irix_primoridal_cpu_fd[0],1941 _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {1942 }1943 PR_ASSERT(rv > 0);1944 }1945 }1946 if (me->cpu->id == 0) {1947 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_irix_primoridal_cpu_fd[0])1948 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0];1949 }1950 #endif1951 }1952 } else if (nfd < 0) {1953 if (errno == EBADF) {1954 FindBadFDs();1955 } else {1956 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",1957 errno));1958 }1959 } else {1960 PR_ASSERT(nfd == 0);1961 /*1962 * compute the new value of _PR_IOQ_TIMEOUT1963 */1964 q = _PR_IOQ(me->cpu).next;1965 _PR_IOQ_MAX_OSFD(me->cpu) = -1;1966 _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;1967 while (q != &_PR_IOQ(me->cpu)) {1968 PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);1969 _PRUnixPollDesc *pds = pq->pds;1970 _PRUnixPollDesc *epds = pds + pq->npds;1971 PRInt32 pq_max_osfd = -1;1972 1973 q = q->next;1974 for (; pds < epds; pds++) {1975 if (pds->osfd > pq_max_osfd) {1976 pq_max_osfd = pds->osfd;1977 }1978 }1979 if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))1980 _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;1981 if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)1982 _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;1983 }1984 if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {1985 if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])1986 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];1987 }1988 }1989 #endif /* _PR_USE_POLL */1990 _PR_MD_IOQ_UNLOCK();1991 }1992 1993 void _MD_Wakeup_CPUs()1994 {1995 PRInt32 rv, data;1996 1997 data = 0;1998 rv = write(_pr_md_pipefd[1], &data, 1);1999 2000 while ((rv < 0) && (errno == EAGAIN)) {2001 /*2002 * pipe full, read all data in pipe to empty it2003 */2004 while ((rv =2005 read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))2006 == PIPE_BUF) {2007 }2008 PR_ASSERT((rv > 0) ||2009 ((rv == -1) && (errno == EAGAIN)));2010 rv = write(_pr_md_pipefd[1], &data, 1);2011 }2012 }2013 2014 2015 void _MD_InitCPUS()2016 {2017 PRInt32 rv, flags;2018 PRThread *me = _MD_CURRENT_THREAD();2019 2020 rv = pipe(_pr_md_pipefd);2021 PR_ASSERT(rv == 0);2022 _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];2023 #ifndef _PR_USE_POLL2024 FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));2025 #endif2026 2027 flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);2028 fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);2029 flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);2030 fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);2031 }2032 2033 /*2034 ** Unix SIGALRM (clock) signal handler2035 */2036 static void ClockInterruptHandler()2037 {2038 int olderrno;2039 PRUintn pri;2040 _PRCPU *cpu = _PR_MD_CURRENT_CPU();2041 PRThread *me = _MD_CURRENT_THREAD();2042 2043 #ifdef SOLARIS2044 if (!me || _PR_IS_NATIVE_THREAD(me)) {2045 _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;2046 return;2047 }2048 #endif2049 2050 if (_PR_MD_GET_INTSOFF() != 0) {2051 cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;2052 return;2053 }2054 _PR_MD_SET_INTSOFF(1);2055 2056 olderrno = errno;2057 _PR_ClockInterrupt();2058 errno = olderrno;2059 2060 /*2061 ** If the interrupt wants a resched or if some other thread at2062 ** the same priority needs the cpu, reschedule.2063 */2064 pri = me->priority;2065 if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {2066 #ifdef _PR_NO_PREEMPT2067 cpu->resched = PR_TRUE;2068 if (pr_interruptSwitchHook) {2069 (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);2070 }2071 #else /* _PR_NO_PREEMPT */2072 /*2073 ** Re-enable unix interrupts (so that we can use2074 ** setjmp/longjmp for context switching without having to2075 ** worry about the signal state)2076 */2077 sigprocmask(SIG_SETMASK, &empty_set, 0);2078 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));2079 2080 if(!(me->flags & _PR_IDLE_THREAD)) {2081 _PR_THREAD_LOCK(me);2082 me->state = _PR_RUNNABLE;2083 me->cpu = cpu;2084 _PR_RUNQ_LOCK(cpu);2085 _PR_ADD_RUNQ(me, cpu, pri);2086 _PR_RUNQ_UNLOCK(cpu);2087 _PR_THREAD_UNLOCK(me);2088 } else2089 me->state = _PR_RUNNABLE;2090 _MD_SWITCH_CONTEXT(me);2091 PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));2092 #endif /* _PR_NO_PREEMPT */2093 }2094 /*2095 * Because this thread could be running on a different cpu after2096 * a context switch the current cpu should be accessed and the2097 * value of the 'cpu' variable should not be used.2098 */2099 _PR_MD_SET_INTSOFF(0);2100 }2101 2102 /*2103 * On HP-UX 9, we have to use the sigvector() interface to restart2104 * interrupted system calls, because sigaction() does not have the2105 * SA_RESTART flag.2106 */2107 2108 #ifdef HPUX92109 static void HPUX9_ClockInterruptHandler(2110 int sig,2111 int code,2112 struct sigcontext *scp)2113 {2114 ClockInterruptHandler();2115 scp->sc_syscall_action = SIG_RESTART;2116 }2117 #endif /* HPUX9 */2118 2119 /* # of milliseconds per clock tick that we will use */2120 #define MSEC_PER_TICK 502121 2122 2123 void _MD_StartInterrupts()2124 {2125 char *eval;2126 2127 if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {2128 if (atoi(eval) == 0)2129 _nspr_noclock = 0;2130 else2131 _nspr_noclock = 1;2132 }2133 2134 #ifndef _PR_NO_CLOCK_TIMER2135 if (!_nspr_noclock) {2136 _MD_EnableClockInterrupts();2137 }2138 #endif2139 }2140 2141 void _MD_StopInterrupts()2142 {2143 sigprocmask(SIG_BLOCK, &timer_set, 0);2144 }2145 2146 void _MD_EnableClockInterrupts()2147 {2148 struct itimerval itval;2149 extern PRUintn _pr_numCPU;2150 #ifdef HPUX92151 struct sigvec vec;2152 2153 vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler;2154 vec.sv_mask = 0;2155 vec.sv_flags = 0;2156 sigvector(SIGALRM, &vec, 0);2157 #else2158 struct sigaction vtact;2159 2160 vtact.sa_handler = (void (*)()) ClockInterruptHandler;2161 sigemptyset(&vtact.sa_mask);2162 vtact.sa_flags = SA_RESTART;2163 sigaction(SIGALRM, &vtact, 0);2164 #endif /* HPUX9 */2165 2166 PR_ASSERT(_pr_numCPU == 1);2167 itval.it_interval.tv_sec = 0;2168 itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;2169 itval.it_value = itval.it_interval;2170 setitimer(ITIMER_REAL, &itval, 0);2171 }2172 2173 void _MD_DisableClockInterrupts()2174 {2175 struct itimerval itval;2176 extern PRUintn _pr_numCPU;2177 2178 PR_ASSERT(_pr_numCPU == 1);2179 itval.it_interval.tv_sec = 0;2180 itval.it_interval.tv_usec = 0;2181 itval.it_value = itval.it_interval;2182 setitimer(ITIMER_REAL, &itval, 0);2183 }2184 2185 void _MD_BlockClockInterrupts()2186 {2187 sigprocmask(SIG_BLOCK, &timer_set, 0);2188 }2189 2190 void _MD_UnblockClockInterrupts()2191 {2192 sigprocmask(SIG_UNBLOCK, &timer_set, 0);2193 }2194 2195 void _MD_MakeNonblock(PRFileDesc *fd)2196 {2197 PRInt32 osfd = fd->secret->md.osfd;2198 int flags;2199 2200 if (osfd <= 2) {2201 /* Don't mess around with stdin, stdout or stderr */2202 return;2203 }2204 flags = fcntl(osfd, F_GETFL, 0);2205 2206 /*2207 * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible.2208 * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O),2209 * otherwise connect() still blocks and can be interrupted by SIGALRM.2210 */2211 2212 #ifdef SUNOS42213 fcntl(osfd, F_SETFL, flags | FNDELAY);2214 #else2215 fcntl(osfd, F_SETFL, flags | O_NONBLOCK);2216 #endif2217 }2218 2219 PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode)2220 {2221 PRInt32 osflags;2222 PRInt32 rv, err;2223 2224 if (flags & PR_RDWR) {2225 osflags = O_RDWR;2226 } else if (flags & PR_WRONLY) {2227 osflags = O_WRONLY;2228 } else {2229 osflags = O_RDONLY;2230 }2231 2232 if (flags & PR_EXCL)2233 osflags |= O_EXCL;2234 if (flags & PR_APPEND)2235 osflags |= O_APPEND;2236 if (flags & PR_TRUNCATE)2237 osflags |= O_TRUNC;2238 if (flags & PR_SYNC) {2239 #if defined(O_SYNC)2240 osflags |= O_SYNC;2241 #elif defined(O_FSYNC)2242 osflags |= O_FSYNC;2243 #else2244 #error "Neither O_SYNC nor O_FSYNC is defined on this platform"2245 #endif2246 }2247 2248 /*2249 ** On creations we hold the 'create' lock in order to enforce2250 ** the semantics of PR_Rename. (see the latter for more details)2251 */2252 if (flags & PR_CREATE_FILE)2253 {2254 osflags |= O_CREAT;2255 if (NULL !=_pr_rename_lock)2256 PR_Lock(_pr_rename_lock);2257 }2258 2259 rv = _md_iovector._open64(name, osflags, mode);2260 2261 if (rv < 0) {2262 err = _MD_ERRNO();2263 _PR_MD_MAP_OPEN_ERROR(err);2264 }2265 2266 if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))2267 PR_Unlock(_pr_rename_lock);2268 return rv;2269 }2270 2271 PRIntervalTime intr_timeout_ticks;2272 2273 #if defined(SOLARIS) || defined(IRIX)2274 static void sigsegvhandler() {2275 fprintf(stderr,"Received SIGSEGV\n");2276 fflush(stderr);2277 pause();2278 }2279 2280 static void sigaborthandler() {2281 fprintf(stderr,"Received SIGABRT\n");2282 fflush(stderr);2283 pause();2284 }2285 2286 static void sigbushandler() {2287 fprintf(stderr,"Received SIGBUS\n");2288 fflush(stderr);2289 pause();2290 }2291 #endif /* SOLARIS, IRIX */2292 2293 #endif /* !defined(_PR_PTHREADS) */2294 2295 99 void _MD_query_fd_inheritable(PRFileDesc *fd) 2296 100 { … … 2820 624 sigemptyset(&timer_set); 2821 625 2822 #if !defined(_PR_PTHREADS)2823 2824 sigaddset(&timer_set, SIGALRM);2825 sigemptyset(&empty_set);2826 intr_timeout_ticks =2827 PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);2828 2829 #if defined(SOLARIS) || defined(IRIX)2830 2831 if (getenv("NSPR_SIGSEGV_HANDLE")) {2832 sigact.sa_handler = sigsegvhandler;2833 sigact.sa_flags = 0;2834 sigact.sa_mask = timer_set;2835 sigaction(SIGSEGV, &sigact, 0);2836 }2837 2838 if (getenv("NSPR_SIGABRT_HANDLE")) {2839 sigact.sa_handler = sigaborthandler;2840 sigact.sa_flags = 0;2841 sigact.sa_mask = timer_set;2842 sigaction(SIGABRT, &sigact, 0);2843 }2844 2845 if (getenv("NSPR_SIGBUS_HANDLE")) {2846 sigact.sa_handler = sigbushandler;2847 sigact.sa_flags = 0;2848 sigact.sa_mask = timer_set;2849 sigaction(SIGBUS, &sigact, 0);2850 }2851 2852 #endif2853 #endif /* !defined(_PR_PTHREADS) */2854 2855 /*2856 * Under HP-UX DCE threads, sigaction() installs a per-thread2857 * handler, so we use sigvector() to install a process-wide2858 * handler.2859 */2860 #if defined(HPUX) && defined(_PR_DCETHREADS)2861 {2862 struct sigvec vec;2863 2864 vec.sv_handler = SIG_IGN;2865 vec.sv_mask = 0;2866 vec.sv_flags = 0;2867 rv = sigvector(SIGPIPE, &vec, NULL);2868 PR_ASSERT(0 == rv);2869 }2870 #else2871 626 sigact.sa_handler = SIG_IGN; 2872 627 sigemptyset(&sigact.sa_mask); … … 2874 629 rv = sigaction(SIGPIPE, &sigact, 0); 2875 630 PR_ASSERT(0 == rv); 2876 #endif /* HPUX && _PR_DCETHREADS */2877 631 2878 632 _pr_rename_lock = PR_NewLock(); … … 2887 641 _PR_InitIOV(); /* one last hack */ 2888 642 } 2889 2890 #if !defined(_PR_PTHREADS)2891 2892 /*2893 * Variables used by the GC code, initialized in _MD_InitSegs().2894 */2895 static PRInt32 _pr_zero_fd = -1;2896 static PRLock *_pr_md_lock = NULL;2897 2898 /*2899 * _MD_InitSegs --2900 *2901 * This is Unix's version of _PR_MD_INIT_SEGS(), which is2902 * called by _PR_InitSegs(), which in turn is called by2903 * PR_Init().2904 */2905 void _MD_InitSegs(void)2906 {2907 #ifdef DEBUG2908 /*2909 ** Disable using mmap(2) if NSPR_NO_MMAP is set2910 */2911 if (getenv("NSPR_NO_MMAP")) {2912 _pr_zero_fd = -2;2913 return;2914 }2915 #endif2916 _pr_zero_fd = open("/dev/zero",O_RDWR , 0);2917 /* Prevent the fd from being inherited by child processes */2918 fcntl(_pr_zero_fd, F_SETFD, FD_CLOEXEC);2919 _pr_md_lock = PR_NewLock();2920 }2921 2922 PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)2923 {2924 static char *lastaddr = (char*) _PR_STACK_VMBASE;2925 PRStatus retval = PR_SUCCESS;2926 int prot;2927 void *rv;2928 2929 PR_ASSERT(seg != 0);2930 PR_ASSERT(size != 0);2931 2932 PR_Lock(_pr_md_lock);2933 if (_pr_zero_fd < 0) {2934 from_heap:2935 seg->vaddr = PR_MALLOC(size);2936 if (!seg->vaddr) {2937 retval = PR_FAILURE;2938 }2939 else {2940 seg->size = size;2941 }2942 goto exit;2943 }2944 2945 prot = PROT_READ|PROT_WRITE;2946 /*2947 * On Alpha Linux, the user-level thread stack needs2948 * to be made executable because longjmp/signal seem2949 * to put machine instructions on the stack.2950 */2951 #if defined(LINUX) && defined(__alpha)2952 prot |= PROT_EXEC;2953 #endif2954 rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,2955 _MD_MMAP_FLAGS,2956 _pr_zero_fd, 0);2957 if (rv == (void*)-1) {2958 goto from_heap;2959 }2960 lastaddr += size;2961 seg->vaddr = rv;2962 seg->size = size;2963 seg->flags = _PR_SEG_VM;2964 2965 exit:2966 PR_Unlock(_pr_md_lock);2967 return retval;2968 }2969 2970 void _MD_FreeSegment(PRSegment *seg)2971 {2972 if (seg->flags & _PR_SEG_VM)2973 (void) munmap(seg->vaddr, seg->size);2974 else2975 PR_DELETE(seg->vaddr);2976 }2977 2978 #endif /* _PR_PTHREADS */2979 643 2980 644 /* … … 3023 687 } 3024 688 3025 #if !defined(_PR_PTHREADS)3026 /*3027 * Wait for I/O on multiple descriptors.3028 *3029 * Return 0 if timed out, return -1 if interrupted,3030 * else return the number of ready descriptors.3031 */3032 PRInt32 _PR_WaitForMultipleFDs(3033 _PRUnixPollDesc *unixpds,3034 PRInt32 pdcnt,3035 PRIntervalTime timeout)3036 {3037 PRPollQueue pq;3038 PRIntn is;3039 PRInt32 rv;3040 _PRCPU *io_cpu;3041 _PRUnixPollDesc *unixpd, *eunixpd;3042 PRThread *me = _PR_MD_CURRENT_THREAD();3043 3044 PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));3045 3046 if (_PR_PENDING_INTERRUPT(me)) {3047 me->flags &= ~_PR_INTERRUPT;3048 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);3049 return -1;3050 }3051 3052 pq.pds = unixpds;3053 pq.npds = pdcnt;3054 3055 _PR_INTSOFF(is);3056 _PR_MD_IOQ_LOCK();3057 _PR_THREAD_LOCK(me);3058 3059 pq.thr = me;3060 io_cpu = me->cpu;3061 pq.on_ioq = PR_TRUE;3062 pq.timeout = timeout;3063 _PR_ADD_TO_IOQ(pq, me->cpu);3064 3065 #if !defined(_PR_USE_POLL)3066 eunixpd = unixpds + pdcnt;3067 for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {3068 PRInt32 osfd = unixpd->osfd;3069 if (unixpd->in_flags & _PR_UNIX_POLL_READ) {3070 FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));3071 _PR_FD_READ_CNT(me->cpu)[osfd]++;3072 }3073 if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) {3074 FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));3075 (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;3076 }3077 if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) {3078 FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));3079 (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;3080 }3081 if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) {3082 _PR_IOQ_MAX_OSFD(me->cpu) = osfd;3083 }3084 }3085 #endif /* !defined(_PR_USE_POLL) */3086 3087 if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) {3088 _PR_IOQ_TIMEOUT(me->cpu) = timeout;3089 }3090 3091 _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;3092 3093 _PR_SLEEPQ_LOCK(me->cpu);3094 _PR_ADD_SLEEPQ(me, timeout);3095 me->state = _PR_IO_WAIT;3096 me->io_pending = PR_TRUE;3097 me->io_suspended = PR_FALSE;3098 _PR_SLEEPQ_UNLOCK(me->cpu);3099 _PR_THREAD_UNLOCK(me);3100 _PR_MD_IOQ_UNLOCK();3101 3102 _PR_MD_WAIT(me, timeout);3103 3104 me->io_pending = PR_FALSE;3105 me->io_suspended = PR_FALSE;3106 3107 /*3108 * This thread should run on the same cpu on which it was blocked; when3109 * the IO request times out the fd sets and fd counts for the3110 * cpu are updated below.3111 */3112 PR_ASSERT(me->cpu == io_cpu);3113 3114 /*3115 ** If we timed out the pollq might still be on the ioq. Remove it3116 ** before continuing.3117 */3118 if (pq.on_ioq) {3119 _PR_MD_IOQ_LOCK();3120 /*3121 * Need to check pq.on_ioq again3122 */3123 if (pq.on_ioq) {3124 PR_REMOVE_LINK(&pq.links);3125 #ifndef _PR_USE_POLL3126 eunixpd = unixpds + pdcnt;3127 for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {3128 PRInt32 osfd = unixpd->osfd;3129 PRInt16 in_flags = unixpd->in_flags;3130 3131 if (in_flags & _PR_UNIX_POLL_READ) {3132 if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)3133 FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));3134 }3135 if (in_flags & _PR_UNIX_POLL_WRITE) {3136 if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)3137 FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));3138 }3139 if (in_flags & _PR_UNIX_POLL_EXCEPT) {3140 if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)3141 FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));3142 }3143 }3144 #endif /* _PR_USE_POLL */3145 PR_ASSERT(pq.npds == pdcnt);3146 _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;3147 PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);3148 }3149 _PR_MD_IOQ_UNLOCK();3150 }3151 /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */3152 if (1 == pdcnt) {3153 _PR_FAST_INTSON(is);3154 } else {3155 _PR_INTSON(is);3156 }3157 3158 if (_PR_PENDING_INTERRUPT(me)) {3159 me->flags &= ~_PR_INTERRUPT;3160 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);3161 return -1;3162 }3163 3164 rv = 0;3165 if (pq.on_ioq == PR_FALSE) {3166 /* Count the number of ready descriptors */3167 while (--pdcnt >= 0) {3168 if (unixpds->out_flags != 0) {3169 rv++;3170 }3171 unixpds++;3172 }3173 }3174 3175 return rv;3176 }3177 3178 /*3179 * Unblock threads waiting for I/O3180 * used when interrupting threads3181 *3182 * NOTE: The thread lock should held when this function is called.3183 * On return, the thread lock is released.3184 */3185 void _PR_Unblock_IO_Wait(PRThread *thr)3186 {3187 int pri = thr->priority;3188 _PRCPU *cpu = thr->cpu;3189 3190 /*3191 * GLOBAL threads wakeup periodically to check for interrupt3192 */3193 if (_PR_IS_NATIVE_THREAD(thr)) {3194 _PR_THREAD_UNLOCK(thr);3195 return;3196 }3197 3198 PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));3199 _PR_SLEEPQ_LOCK(cpu);3200 _PR_DEL_SLEEPQ(thr, PR_TRUE);3201 _PR_SLEEPQ_UNLOCK(cpu);3202 3203 PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));3204 thr->state = _PR_RUNNABLE;3205 _PR_RUNQ_LOCK(cpu);3206 _PR_ADD_RUNQ(thr, cpu, pri);3207 _PR_RUNQ_UNLOCK(cpu);3208 _PR_THREAD_UNLOCK(thr);3209 _PR_MD_WAKEUP_WAITER(thr);3210 }3211 #endif /* !defined(_PR_PTHREADS) */3212 3213 689 /* 3214 690 * When a nonblocking connect has completed, determine whether it … … 3221 697 int _MD_unix_get_nonblocking_connect_error(int osfd) 3222 698 { 3223 #if defined(NTO)3224 /* Neutrino does not support the SO_ERROR socket option */3225 PRInt32 rv;3226 PRNetAddr addr;3227 _PRSockLen_t addrlen = sizeof(addr);3228 3229 /* Test to see if we are using the Tiny TCP/IP Stack or the Full one. */3230 struct statvfs superblock;3231 rv = fstatvfs(osfd, &superblock);3232 if (rv == 0) {3233 if (strcmp(superblock.f_basetype, "ttcpip") == 0) {3234 /* Using the Tiny Stack! */3235 rv = getpeername(osfd, (struct sockaddr *) &addr,3236 (_PRSockLen_t *) &addrlen);3237 if (rv == -1) {3238 int errno_copy = errno; /* make a copy so I don't3239 * accidentally reset */3240 3241 if (errno_copy == ENOTCONN) {3242 struct stat StatInfo;3243 rv = fstat(osfd, &StatInfo);3244 if (rv == 0) {3245 time_t current_time = time(NULL);3246 3247 /*3248 * this is a real hack, can't explain why it3249 * works it just does3250 */3251 if (abs(current_time - StatInfo.st_atime) < 5) {3252 return ECONNREFUSED;3253 } else {3254 return ETIMEDOUT;3255 }3256 } else {3257 return ECONNREFUSED;3258 }3259 } else {3260 return errno_copy;3261 }3262 } else {3263 /* No Error */3264 return 0;3265 }3266 } else {3267 /* Have the FULL Stack which supports SO_ERROR */3268 /* Hasn't been written yet, never been tested! */3269 /* [email protected] */3270 3271 int err;3272 _PRSockLen_t optlen = sizeof(err);3273 3274 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,3275 (char *) &err, &optlen) == -1) {3276 return errno;3277 } else {3278 return err;3279 }3280 }3281 } else {3282 return ECONNREFUSED;3283 }3284 #elif defined(NCR) || defined(UNIXWARE) || defined(SNI) || defined(NEC)3285 /*3286 * getsockopt() fails with EPIPE, so use getmsg() instead.3287 */3288 3289 int rv;3290 int flags = 0;3291 rv = getmsg(osfd, NULL, NULL, &flags);3292 PR_ASSERT(-1 == rv || 0 == rv);3293 if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {3294 return errno;3295 }3296 return 0; /* no error */3297 #else3298 699 int err; 3299 700 _PRSockLen_t optlen = sizeof(err); … … 3303 704 return err; 3304 705 } 3305 #endif3306 706 } 3307 707 -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c
r101795 r101805 173 173 _PR_InitLocks(); 174 174 _PR_InitAtomic(); 175 _PR_InitSegs();176 175 _PR_InitTPD(); 177 176 _PR_InitEnv(); … … 199 198 { 200 199 _PR_InitStuff(); 201 202 /* Enable interrupts */203 #if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)204 _PR_MD_START_INTERRUPTS();205 #endif206 207 200 } 208 201 209 202 PR_IMPLEMENT(void) PR_DisableClockInterrupts(void) 210 203 { 211 #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)212 if (!_pr_initialized) {213 _PR_InitStuff();214 } else {215 _PR_MD_DISABLE_CLOCK_INTERRUPTS();216 }217 #endif218 204 } 219 205 220 206 PR_IMPLEMENT(void) PR_EnableClockInterrupts(void) 221 207 { 222 #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)223 if (!_pr_initialized) {224 _PR_InitStuff();225 }226 _PR_MD_ENABLE_CLOCK_INTERRUPTS();227 #endif228 208 } 229 209 230 210 PR_IMPLEMENT(void) PR_BlockClockInterrupts(void) 231 211 { 232 #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)233 _PR_MD_BLOCK_CLOCK_INTERRUPTS();234 #endif235 212 } 236 213 237 214 PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void) 238 215 { 239 #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)240 _PR_MD_UNBLOCK_CLOCK_INTERRUPTS();241 #endif242 216 } 243 217 -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c
r101793 r101805 40 40 ** Descritpion: Implemenation of I/O methods for pthreads 41 41 */ 42 43 #if defined(_PR_PTHREADS)44 42 45 43 #if defined(_PR_POLL_WITH_SELECT) … … 4180 4178 return rv; 4181 4179 } 4182 #endif /* defined(_PR_PTHREADS) */4183 4180 4184 4181 #ifdef MOZ_UNICODE -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptsynch.c
r101769 r101805 42 42 */ 43 43 44 #if defined(_PR_PTHREADS)45 46 44 #include "primpl.h" 47 45 … … 1126 1124 } /* PRP_NakedBroadcast */ 1127 1125 1128 #endif /* defined(_PR_PTHREADS) */1129 1130 1126 /* ptsynch.c */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c
r101793 r101805 41 41 ** Exports: ptthread.h 42 42 */ 43 44 #if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS)45 43 46 44 #include "prlog.h" … … 1560 1558 #endif /* !defined(_PR_DCETHREADS) */ 1561 1559 1562 #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */1563 1564 1560 /* ptthread.c */
Note:
See TracChangeset
for help on using the changeset viewer.