📄 btthread.c
字号:
PRThreadStack *stack){ /* PR_GetCurrentThread() will attach a thread if necessary */ return PR_GetCurrentThread();}PR_IMPLEMENT(void) PR_DetachThread(){ /* we don't support detaching */}PR_IMPLEMENT(PRStatus) PR_JoinThread (PRThread* thred){ status_t eval, status; PR_ASSERT(thred != NULL); if ((thred->state & BT_THREAD_JOINABLE) == 0) { PR_SetError( PR_INVALID_ARGUMENT_ERROR, 0 ); return( PR_FAILURE ); } /* synchronize access to the thread's joinSem */ PR_Lock(joinSemLock); if (thred->md.is_joining) { /* another thread is already waiting to join the specified thread - we must fail */ PR_Unlock(joinSemLock); return PR_FAILURE; } /* let others know we are waiting to join */ thred->md.is_joining = PR_TRUE; if (thred->md.joinSem == B_ERROR) { /* the thread hasn't finished yet - it is our responsibility to allocate a joinSem and wait on it */ thred->md.joinSem = create_sem(0, "join sem"); /* we're done changing the joinSem now */ PR_Unlock(joinSemLock); /* wait for the thread to finish */ while (acquire_sem(thred->md.joinSem) == B_INTERRUPTED); } else { /* the thread has already finished, and has allocated the joinSem itself - let it know it can finally die */ delete_sem(thred->md.joinSem); PR_Unlock(joinSemLock); } /* make sure the thread is dead */ wait_for_thread(thred->md.tid, &eval); return PR_SUCCESS;}PR_IMPLEMENT(PRThread*) PR_GetCurrentThread (){ PRThread* thred; if (!_pr_initialized) _PR_ImplicitInitialization(); thred = (PRThread *)tls_get( tls_prThreadSlot); if (thred == NULL) { /* this thread doesn't have a PRThread structure (it must be a native thread not created by the NSPR) - assimilate it */ thred = _bt_AttachThread(); } PR_ASSERT(NULL != thred); return thred;}PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope (const PRThread* thred){ PR_ASSERT(thred != NULL); return PR_GLOBAL_THREAD;}PR_IMPLEMENT(PRThreadType) PR_GetThreadType (const PRThread* thred){ PR_ASSERT(thred != NULL); return (thred->state & BT_THREAD_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;}PR_IMPLEMENT(PRThreadState) PR_GetThreadState (const PRThread* thred){ PR_ASSERT(thred != NULL); return (thred->state & BT_THREAD_JOINABLE)? PR_JOINABLE_THREAD: PR_UNJOINABLE_THREAD;}PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority (const PRThread* thred){ PR_ASSERT(thred != NULL); return thred->priority;} /* PR_GetThreadPriority */PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri){ PRUint32 bePriority; PR_ASSERT( thred != NULL ); thred->priority = newPri; bePriority = _bt_MapNSPRToNativePriority( newPri ); set_thread_priority( thred->md.tid, bePriority );}PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex (PRUintn* newIndex, PRThreadPrivateDTOR destructor){ int32 index; if (!_pr_initialized) _PR_ImplicitInitialization(); /* reserve the next available tpd slot */ index = atomic_add( &tpd_slotsUsed, 1 ); if (index >= BT_TPD_LIMIT) { /* no slots left - decrement value, then fail */ atomic_add( &tpd_slotsUsed, -1 ); PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return( PR_FAILURE ); } /* allocate a beos-native TLS slot for this index (the new slot automatically contains NULL) */ tpd_beosTLSSlots[index] = tls_allocate(); /* remember the destructor */ tpd_dtors[index] = destructor; *newIndex = (PRUintn)index; return( PR_SUCCESS );}PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate (PRUintn index, void* priv){ void *oldValue; /* ** Sanity checking */ if(index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT) { PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return( PR_FAILURE ); } /* if the old value isn't NULL, and the dtor for this slot isn't NULL, we must destroy the data */ oldValue = tls_get(tpd_beosTLSSlots[index]); if (oldValue != NULL && tpd_dtors[index] != NULL) (*tpd_dtors[index])(oldValue); /* save new value */ tls_set(tpd_beosTLSSlots[index], priv); return( PR_SUCCESS ); }PR_IMPLEMENT(void*) PR_GetThreadPrivate (PRUintn index){ /* make sure the index is valid */ if (index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT) { PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return NULL; } /* return the value */ return tls_get( tpd_beosTLSSlots[index] ); }PR_IMPLEMENT(PRStatus) PR_Interrupt (PRThread* thred){ PRIntn rv; PR_ASSERT(thred != NULL); /* ** there seems to be a bug in beos R5 in which calling ** resume_thread() on a blocked thread returns B_OK instead ** of B_BAD_THREAD_STATE (beos bug #20000422-19095). as such, ** to interrupt a thread, we will simply suspend then resume it ** (no longer call resume_thread(), check for B_BAD_THREAD_STATE, ** the suspend/resume to wake up a blocked thread). this wakes ** up blocked threads properly, and doesn't hurt unblocked threads ** (they simply get stopped then re-started immediately) */ rv = suspend_thread( thred->md.tid ); if( rv != B_NO_ERROR ) { /* this doesn't appear to be a valid thread_id */ PR_SetError( PR_UNKNOWN_ERROR, rv ); return PR_FAILURE; } rv = resume_thread( thred->md.tid ); if( rv != B_NO_ERROR ) { PR_SetError( PR_UNKNOWN_ERROR, rv ); return PR_FAILURE; } return PR_SUCCESS;}PR_IMPLEMENT(void) PR_ClearInterrupt (){}PR_IMPLEMENT(PRStatus) PR_Yield (){ /* we just sleep for long enough to cause a reschedule (100 microseconds) */ snooze(100);}#define BT_MILLION 1000000ULPR_IMPLEMENT(PRStatus) PR_Sleep (PRIntervalTime ticks){ bigtime_t tps; status_t status; if (!_pr_initialized) _PR_ImplicitInitialization(); tps = PR_IntervalToMicroseconds( ticks ); status = snooze(tps); if (status == B_NO_ERROR) return PR_SUCCESS; PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status); return PR_FAILURE;}PR_IMPLEMENT(PRStatus) PR_Cleanup (){ PRThread *me = PR_CurrentThread(); PR_ASSERT(me->state & BT_THREAD_PRIMORD); if ((me->state & BT_THREAD_PRIMORD) == 0) { return PR_FAILURE; } PR_Lock( bt_book.ml ); if (bt_book.threadCount != 0) { /* we'll have to wait for some threads to finish - create a sem to block on */ bt_book.cleanUpSem = create_sem(0, "cleanup sem"); } PR_Unlock( bt_book.ml ); /* note that, if all the user threads were already dead, we wouldn't have created a sem above, so this acquire_sem() will fail immediately */ while (acquire_sem(bt_book.cleanUpSem) == B_INTERRUPTED); return PR_SUCCESS;}PR_IMPLEMENT(void) PR_ProcessExit (PRIntn status){ exit(status);}PRThread *_bt_AttachThread(){ PRThread *thread; thread_info tInfo; /* make sure this thread doesn't already have a PRThread structure */ PR_ASSERT(tls_get(tls_prThreadSlot) == NULL); /* allocate a PRThread structure for this thread */ thread = PR_NEWZAP(PRThread); if (thread == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } /* get the native thread's current state */ get_thread_info(find_thread(NULL), &tInfo); /* initialize new PRThread */ thread->md.tid = tInfo.thread; thread->md.joinSem = B_ERROR; thread->priority = _bt_MapNativeToNSPRPriority(tInfo.priority); /* attached threads are always non-joinable user threads */ thread->state = 0; /* increment user thread count */ PR_Lock(bt_book.ml); bt_book.threadCount++; PR_Unlock(bt_book.ml); /* store this thread's PRThread */ tls_set(tls_prThreadSlot, thread); /* the thread must call _bt_CleanupThread() before it dies, in order to clean up its PRThread, synchronize with the primordial thread, etc. */ on_exit_thread(_bt_CleanupThread, NULL); return thread;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -