⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btthread.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include <kernel/OS.h>#include <support/TLS.h>#include "prlog.h"#include "primpl.h"#include "prcvar.h"#include "prpdce.h"#include <stdlib.h>#include <string.h>#include <signal.h>/* values for PRThread.state */#define BT_THREAD_PRIMORD   0x01    /* this is the primordial thread */#define BT_THREAD_SYSTEM    0x02    /* this is a system thread */#define BT_THREAD_JOINABLE  0x04	/* this is a joinable thread */struct _BT_Bookeeping{    PRLock *ml;                 /* a lock to protect ourselves */	sem_id cleanUpSem;		/* the primoridal thread will block on this							   sem while waiting for the user threads */    PRInt32 threadCount;	/* user thred count */} bt_book = { NULL, B_ERROR, 0 };#define BT_TPD_LIMIT 128	/* number of TPD slots we'll provide (arbitrary) *//* these will be used to map an index returned by PR_NewThreadPrivateIndex()   to the corresponding beos native TLS slot number, and to the destructor   for that slot - note that, because it is allocated globally, this data   will be automatically zeroed for us when the program begins */static int32 tpd_beosTLSSlots[BT_TPD_LIMIT];static PRThreadPrivateDTOR tpd_dtors[BT_TPD_LIMIT];static vint32 tpd_slotsUsed=0;	/* number of currently-allocated TPD slots */static int32 tls_prThreadSlot;	/* TLS slot in which PRThread will be stored *//* this mutex will be used to synchronize access to every   PRThread.md.joinSem and PRThread.md.is_joining (we could   actually allocate one per thread, but that seems a bit excessive,   especially considering that there will probably be little   contention, PR_JoinThread() is allowed to block anyway, and the code   protected by the mutex is short/fast) */static PRLock *joinSemLock;static PRUint32 _bt_MapNSPRToNativePriority( PRThreadPriority priority );static PRThreadPriority _bt_MapNativeToNSPRPriority( PRUint32 priority );static void _bt_CleanupThread(void *arg);static PRThread *_bt_AttachThread();void_PR_InitThreads (PRThreadType type, PRThreadPriority priority,                 PRUintn maxPTDs){    PRThread *primordialThread;    PRUint32  beThreadPriority;	/* allocate joinSem mutex */	joinSemLock = PR_NewLock();	if (joinSemLock == NULL)	{		PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);		return;    }    /*    ** Create and initialize NSPR structure for our primordial thread.    */        primordialThread = PR_NEWZAP(PRThread);    if( NULL == primordialThread )    {        PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );        return;    }	primordialThread->md.joinSem = B_ERROR;    /*    ** Set the priority to the desired level.    */    beThreadPriority = _bt_MapNSPRToNativePriority( priority );        set_thread_priority( find_thread( NULL ), beThreadPriority );        primordialThread->priority = priority;	/* set the thread's state - note that the thread is not joinable */    primordialThread->state |= BT_THREAD_PRIMORD;	if (type == PR_SYSTEM_THREAD)		primordialThread->state |= BT_THREAD_SYSTEM;    /*    ** Allocate a TLS slot for the PRThread structure (just using    ** native TLS, as opposed to NSPR TPD, will make PR_GetCurrentThread()    ** somewhat faster, and will leave one more TPD slot for our client)    */		tls_prThreadSlot = tls_allocate();    /*    ** Stuff our new PRThread structure into our thread specific    ** slot.    */	tls_set(tls_prThreadSlot, primordialThread);    	/* allocate lock for bt_book */    bt_book.ml = PR_NewLock();    if( NULL == bt_book.ml )    {    	PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );	return;    }}PRUint32_bt_MapNSPRToNativePriority( PRThreadPriority priority )    {    switch( priority )    {    	case PR_PRIORITY_LOW:	 return( B_LOW_PRIORITY );	case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );	case PR_PRIORITY_HIGH:	 return( B_DISPLAY_PRIORITY );	case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );	default:		 return( B_NORMAL_PRIORITY );    }}PRThreadPriority_bt_MapNativeToNSPRPriority(PRUint32 priority)    {	if (priority < B_NORMAL_PRIORITY)		return PR_PRIORITY_LOW;	if (priority < B_DISPLAY_PRIORITY)		return PR_PRIORITY_NORMAL;	if (priority < B_URGENT_DISPLAY_PRIORITY)		return PR_PRIORITY_HIGH;	return PR_PRIORITY_URGENT;}PRUint32_bt_mapNativeToNSPRPriority( int32 priority ){    switch( priority )    {    	case PR_PRIORITY_LOW:	 return( B_LOW_PRIORITY );	case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );	case PR_PRIORITY_HIGH:	 return( B_DISPLAY_PRIORITY );	case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );	default:		 return( B_NORMAL_PRIORITY );    }}/* This method is called by all NSPR threads as they exit */void _bt_CleanupThread(void *arg){	PRThread *me = PR_GetCurrentThread();	int32 i;	/* first, clean up all thread-private data */	for (i = 0; i < tpd_slotsUsed; i++)	{		void *oldValue = tls_get(tpd_beosTLSSlots[i]);		if ( oldValue != NULL && tpd_dtors[i] != NULL )			(*tpd_dtors[i])(oldValue);	}	/* if this thread is joinable, wait for someone to join it */	if (me->state & BT_THREAD_JOINABLE)	{		/* protect access to our joinSem */		PR_Lock(joinSemLock);		if (me->md.is_joining)		{			/* someone is already waiting to join us (they've			   allocated a joinSem for us) - let them know we're			   ready */			delete_sem(me->md.joinSem);			PR_Unlock(joinSemLock);		}		else    {			/* noone is currently waiting for our demise - it			   is our responsibility to allocate the joinSem			   and block on it */			me->md.joinSem = create_sem(0, "join sem");			/* we're done accessing our joinSem */			PR_Unlock(joinSemLock);			/* wait for someone to join us */			while (acquire_sem(me->md.joinSem) == B_INTERRUPTED);	    }	}	/* if this is a user thread, we must update our books */	if ((me->state & BT_THREAD_SYSTEM) == 0)	{		/* synchronize access to bt_book */    PR_Lock( bt_book.ml );		/* decrement the number of currently-alive user threads */	bt_book.threadCount--;		if (bt_book.threadCount == 0 && bt_book.cleanUpSem != B_ERROR) {			/* we are the last user thread, and the primordial thread is			   blocked in PR_Cleanup() waiting for us to finish - notify			   it */			delete_sem(bt_book.cleanUpSem);	}    PR_Unlock( bt_book.ml );	}	/* finally, delete this thread's PRThread */	PR_DELETE(me);}/** * This is a wrapper that all threads invoke that allows us to set some * things up prior to a thread's invocation and clean up after a thread has * exited. */static void*_bt_root (void* arg)	{    PRThread *thred = (PRThread*)arg;    PRIntn rv;    void *privData;    status_t result;    int i;	/* save our PRThread object into our TLS */	tls_set(tls_prThreadSlot, thred);    thred->startFunc(thred->arg);  /* run the dang thing */	/* clean up */	_bt_CleanupThread(NULL);	return 0;}PR_IMPLEMENT(PRThread*)    PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg,                     PRThreadPriority priority, PRThreadScope scope,                     PRThreadState state, PRUint32 stackSize){    PRUint32 bePriority;    PRThread* thred;    if (!_pr_initialized) _PR_ImplicitInitialization();	thred = PR_NEWZAP(PRThread); 	if (thred == NULL)	{        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);        return NULL;    }    thred->md.joinSem = B_ERROR;        thred->arg = arg;        thred->startFunc = start;        thred->priority = priority;	if( state == PR_JOINABLE_THREAD )	{	    thred->state |= BT_THREAD_JOINABLE;	}        /* keep some books */	PR_Lock( bt_book.ml );	if (type == PR_USER_THREAD)	{	    bt_book.threadCount++;        }	PR_Unlock( bt_book.ml );	bePriority = _bt_MapNSPRToNativePriority( priority );        thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread",                                     bePriority, thred);        if (thred->md.tid < B_OK) {            PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid);            PR_DELETE(thred);			return NULL;        }        if (resume_thread(thred->md.tid) < B_OK) {            PR_SetError(PR_UNKNOWN_ERROR, 0);            PR_DELETE(thred);			return NULL;        }    return thred;    }PR_IMPLEMENT(PRThread*)	PR_AttachThread(PRThreadType type, PRThreadPriority priority,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -