michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nspr_pthread_defs_h___ michael@0: #define nspr_pthread_defs_h___ michael@0: michael@0: #include michael@0: #include "prthread.h" michael@0: michael@0: #if defined(PTHREADS_USER) michael@0: /* michael@0: ** Thread Local Storage michael@0: */ michael@0: extern pthread_key_t current_thread_key; michael@0: extern pthread_key_t current_cpu_key; michael@0: extern pthread_key_t last_thread_key; michael@0: extern pthread_key_t intsoff_key; michael@0: michael@0: #define _MD_CURRENT_THREAD() \ michael@0: ((struct PRThread *) pthread_getspecific(current_thread_key)) michael@0: #define _MD_CURRENT_CPU() \ michael@0: ((struct _PRCPU *) pthread_getspecific(current_cpu_key)) michael@0: #define _MD_LAST_THREAD() \ michael@0: ((struct PRThread *) pthread_getspecific(last_thread_key)) michael@0: michael@0: #define _MD_SET_CURRENT_THREAD(newval) \ michael@0: pthread_setspecific(current_thread_key, (void *)newval) michael@0: michael@0: #define _MD_SET_CURRENT_CPU(newval) \ michael@0: pthread_setspecific(current_cpu_key, (void *)newval) michael@0: michael@0: #define _MD_SET_LAST_THREAD(newval) \ michael@0: pthread_setspecific(last_thread_key, (void *)newval) michael@0: michael@0: #define _MD_SET_INTSOFF(_val) michael@0: #define _MD_GET_INTSOFF() 1 michael@0: michael@0: /* michael@0: ** Initialize the thread context preparing it to execute _main. michael@0: */ michael@0: #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ michael@0: PR_BEGIN_MACRO \ michael@0: *status = PR_TRUE; \ michael@0: if (SAVE_CONTEXT(_thread)) { \ michael@0: (*_main)(); \ michael@0: } \ michael@0: _MD_SET_THR_SP(_thread, _sp); \ michael@0: _thread->no_sched = 0; \ michael@0: PR_END_MACRO michael@0: michael@0: #define _MD_SWITCH_CONTEXT(_thread) \ michael@0: PR_BEGIN_MACRO \ michael@0: PR_ASSERT(_thread->no_sched); \ michael@0: if (!SAVE_CONTEXT(_thread)) { \ michael@0: (_thread)->md.errcode = errno; \ michael@0: _MD_SET_LAST_THREAD(_thread); \ michael@0: _PR_Schedule(); \ michael@0: } else { \ michael@0: (_MD_LAST_THREAD())->no_sched = 0; \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: /* michael@0: ** Restore a thread context, saved by _MD_SWITCH_CONTEXT michael@0: */ michael@0: #define _MD_RESTORE_CONTEXT(_thread) \ michael@0: PR_BEGIN_MACRO \ michael@0: errno = (_thread)->md.errcode; \ michael@0: _MD_SET_CURRENT_THREAD(_thread); \ michael@0: _thread->no_sched = 1; \ michael@0: GOTO_CONTEXT(_thread); \ michael@0: PR_END_MACRO michael@0: michael@0: michael@0: /* Machine-dependent (MD) data structures */ michael@0: michael@0: struct _MDThread { michael@0: jmp_buf jb; michael@0: int id; michael@0: int errcode; michael@0: pthread_t pthread; michael@0: pthread_mutex_t pthread_mutex; michael@0: pthread_cond_t pthread_cond; michael@0: int wait; michael@0: }; michael@0: michael@0: struct _MDThreadStack { michael@0: PRInt8 notused; michael@0: }; michael@0: michael@0: struct _MDLock { michael@0: pthread_mutex_t mutex; michael@0: }; michael@0: michael@0: struct _MDSemaphore { michael@0: PRInt8 notused; michael@0: }; michael@0: michael@0: struct _MDCVar { michael@0: pthread_mutex_t mutex; michael@0: }; michael@0: michael@0: struct _MDSegment { michael@0: PRInt8 notused; michael@0: }; michael@0: michael@0: /* michael@0: * md-specific cpu structure field michael@0: */ michael@0: #define _PR_MD_MAX_OSFD FD_SETSIZE michael@0: michael@0: struct _MDCPU_Unix { michael@0: PRCList ioQ; michael@0: PRUint32 ioq_timeout; michael@0: PRInt32 ioq_max_osfd; michael@0: PRInt32 ioq_osfd_cnt; michael@0: #ifndef _PR_USE_POLL michael@0: fd_set fd_read_set, fd_write_set, fd_exception_set; michael@0: PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], michael@0: fd_exception_cnt[_PR_MD_MAX_OSFD]; michael@0: #else michael@0: struct pollfd *ioq_pollfds; michael@0: int ioq_pollfds_size; michael@0: #endif /* _PR_USE_POLL */ michael@0: }; michael@0: michael@0: #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) michael@0: #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) michael@0: #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) michael@0: #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) michael@0: #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) michael@0: #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) michael@0: #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) michael@0: #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) michael@0: #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) michael@0: #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) michael@0: #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) michael@0: #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) michael@0: #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) michael@0: michael@0: #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 michael@0: michael@0: struct _MDCPU { michael@0: jmp_buf jb; michael@0: pthread_t pthread; michael@0: struct _MDCPU_Unix md_unix; michael@0: }; michael@0: michael@0: /* michael@0: #define _MD_NEW_LOCK(lock) PR_SUCCESS michael@0: #define _MD_FREE_LOCK(lock) michael@0: #define _MD_LOCK(lock) michael@0: #define _MD_UNLOCK(lock) michael@0: */ michael@0: michael@0: extern pthread_mutex_t _pr_heapLock; michael@0: michael@0: #define _PR_LOCK(lock) pthread_mutex_lock(lock) michael@0: michael@0: #define _PR_UNLOCK(lock) pthread_mutex_unlock(lock) michael@0: michael@0: michael@0: #define _PR_LOCK_HEAP() { \ michael@0: if (_pr_primordialCPU) { \ michael@0: _PR_LOCK(_pr_heapLock); \ michael@0: } michael@0: michael@0: #define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \ michael@0: _PR_UNLOCK(_pr_heapLock); \ michael@0: } \ michael@0: } michael@0: michael@0: NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md); michael@0: NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp); michael@0: michael@0: #define _MD_LOCK(_lockp) _PR_LOCK(&(_lockp)->mutex) michael@0: #define _MD_UNLOCK(_lockp) _PR_UNLOCK(&(_lockp)->mutex) michael@0: michael@0: #define _MD_INIT_IO() michael@0: #define _MD_IOQ_LOCK() michael@0: #define _MD_IOQ_UNLOCK() michael@0: #define _MD_CHECK_FOR_EXIT() michael@0: michael@0: NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread); michael@0: #define _MD_INIT_THREAD _MD_InitThread michael@0: #define _MD_INIT_ATTACHED_THREAD _MD_InitThread michael@0: michael@0: NSPR_API(void) _MD_ExitThread(struct PRThread *thread); michael@0: #define _MD_EXIT_THREAD _MD_ExitThread michael@0: michael@0: NSPR_API(void) _MD_SuspendThread(struct PRThread *thread); michael@0: #define _MD_SUSPEND_THREAD _MD_SuspendThread michael@0: michael@0: NSPR_API(void) _MD_ResumeThread(struct PRThread *thread); michael@0: #define _MD_RESUME_THREAD _MD_ResumeThread michael@0: michael@0: NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread); michael@0: #define _MD_SUSPEND_CPU _MD_SuspendCPU michael@0: michael@0: NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread); michael@0: #define _MD_RESUME_CPU _MD_ResumeCPU michael@0: michael@0: #define _MD_BEGIN_SUSPEND_ALL() michael@0: #define _MD_END_SUSPEND_ALL() michael@0: #define _MD_BEGIN_RESUME_ALL() michael@0: #define _MD_END_RESUME_ALL() michael@0: michael@0: NSPR_API(void) _MD_EarlyInit(void); michael@0: #define _MD_EARLY_INIT _MD_EarlyInit michael@0: michael@0: #define _MD_FINAL_INIT _PR_UnixInit michael@0: michael@0: NSPR_API(void) _MD_InitLocks(void); michael@0: #define _MD_INIT_LOCKS _MD_InitLocks michael@0: michael@0: NSPR_API(void) _MD_CleanThread(struct PRThread *thread); michael@0: #define _MD_CLEAN_THREAD _MD_CleanThread michael@0: michael@0: NSPR_API(PRStatus) _MD_CreateThread( michael@0: struct PRThread *thread, michael@0: void (*start) (void *), michael@0: PRThreadPriority priority, michael@0: PRThreadScope scope, michael@0: PRThreadState state, michael@0: PRUint32 stackSize); michael@0: #define _MD_CREATE_THREAD _MD_CreateThread michael@0: michael@0: extern void _MD_CleanupBeforeExit(void); michael@0: #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit michael@0: michael@0: NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu); michael@0: #define _MD_INIT_RUNNING_CPU _MD_InitRunningCPU michael@0: michael@0: /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and michael@0: * awaken a thread which is waiting on a lock or cvar. michael@0: */ michael@0: NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout); michael@0: #define _MD_WAIT _MD_wait michael@0: michael@0: NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *); michael@0: #define _MD_WAKEUP_WAITER _MD_WakeupWaiter michael@0: michael@0: NSPR_API(void) _MD_SetPriority(struct _MDThread *thread, michael@0: PRThreadPriority newPri); michael@0: #define _MD_SET_PRIORITY _MD_SetPriority michael@0: michael@0: #endif /* PTHREADS_USER */ michael@0: michael@0: #endif /* nspr_pthread_defs_h___ */