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

📄 ntthread.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * 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 "primpl.h"#include <process.h>  /* for _beginthreadex() */extern void _PR_Win32InitTimeZone(void);  /* defined in ntmisc.c *//* --- globals ------------------------------------------------ */PRLock                       *_pr_schedLock = NULL;_PRInterruptTable             _pr_interruptTable[] = { { 0 } };BOOL _pr_use_static_tls = TRUE;__declspec(thread) PRThread  *_pr_current_fiber;__declspec(thread) PRThread  *_pr_fiber_last_run;__declspec(thread) _PRCPU    *_pr_current_cpu;__declspec(thread) PRUintn    _pr_ints_off;DWORD _pr_currentFiberIndex;DWORD _pr_lastFiberIndex;DWORD _pr_currentCPUIndex;DWORD _pr_intsOffIndex;_MDLock                       _nt_idleLock;PRCList                       _nt_idleList;PRUint32                        _nt_idleCount;extern __declspec(thread) PRThread *_pr_io_restarted_io;extern DWORD _pr_io_restartedIOIndex;/* Must check the restarted_io *before* decrementing no_sched to 0 */#define POST_SWITCH_WORK() \    PR_BEGIN_MACRO \        PRThread *restarted_io = \            (_pr_use_static_tls ? _pr_io_restarted_io \            : (PRThread *) TlsGetValue(_pr_io_restartedIOIndex)); \        if (restarted_io) { \            _nt_handle_restarted_io(restarted_io); \        } \        _PR_MD_LAST_THREAD()->no_sched = 0; \    PR_END_MACROvoid_nt_handle_restarted_io(PRThread *restarted_io){    /* After the switch we can resume an IO if needed.     * XXXMB - this needs to be done in create thread, since that could     * be the result for a context switch too..     */    PR_ASSERT(restarted_io->io_suspended == PR_TRUE);    PR_ASSERT(restarted_io->md.thr_bound_cpu == restarted_io->cpu);    _PR_THREAD_LOCK(restarted_io);    if (restarted_io->io_pending == PR_FALSE) {        /* The IO already completed, put us back on the runq. */        int pri = restarted_io->priority;        restarted_io->state = _PR_RUNNABLE;        _PR_RUNQ_LOCK(restarted_io->cpu);        _PR_ADD_RUNQ(restarted_io, restarted_io->cpu, pri);        _PR_RUNQ_UNLOCK(restarted_io->cpu);    } else {        _PR_SLEEPQ_LOCK(restarted_io->cpu);        _PR_ADD_SLEEPQ(restarted_io, restarted_io->sleep);        _PR_SLEEPQ_UNLOCK(restarted_io->cpu);    }    restarted_io->io_suspended = PR_FALSE;    restarted_io->md.thr_bound_cpu = NULL;    _PR_THREAD_UNLOCK(restarted_io);    if (_pr_use_static_tls) {        _pr_io_restarted_io = NULL;    } else {        TlsSetValue(_pr_io_restartedIOIndex, NULL);    }}void_PR_MD_EARLY_INIT(){    _MD_NEW_LOCK( &_nt_idleLock );    _nt_idleCount = 0;    PR_INIT_CLIST(&_nt_idleList);    _PR_Win32InitTimeZone();#if 0    /* Make the clock tick at least once per millisecond */    if ( timeBeginPeriod(1) == TIMERR_NOCANDO) {        /* deep yoghurt; clock doesn't tick fast enough! */        PR_ASSERT(0);    }#endif    if (!_pr_use_static_tls) {        _pr_currentFiberIndex = TlsAlloc();        _pr_lastFiberIndex = TlsAlloc();        _pr_currentCPUIndex = TlsAlloc();        _pr_intsOffIndex = TlsAlloc();        _pr_io_restartedIOIndex = TlsAlloc();    }}void _PR_MD_CLEANUP_BEFORE_EXIT(void){    _PR_NT_FreeSids();    WSACleanup();    if (!_pr_use_static_tls) {        TlsFree(_pr_currentFiberIndex);        TlsFree(_pr_lastFiberIndex);        TlsFree(_pr_currentCPUIndex);        TlsFree(_pr_intsOffIndex);        TlsFree(_pr_io_restartedIOIndex);    }}PRStatus_PR_MD_INIT_THREAD(PRThread *thread){    thread->md.overlapped.ioModel = _MD_BlockingIO;    thread->md.overlapped.data.mdThread = &thread->md;    if (thread->flags & _PR_GLOBAL_SCOPE) {        if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {            /*            ** Warning:            ** --------            ** NSPR requires a real handle to every thread.            ** GetCurrentThread() returns a pseudo-handle which            ** is not suitable for some thread operations (e.g.,            ** suspending).  Therefore, get a real handle from            ** the pseudo handle via DuplicateHandle(...)            */            DuplicateHandle(                    GetCurrentProcess(),     /* Process of source handle */                    GetCurrentThread(),      /* Pseudo Handle to dup */                    GetCurrentProcess(),     /* Process of handle */                    &(thread->md.handle),    /* resulting handle */                    0L,                      /* access flags */                    FALSE,                   /* Inheritable */                    DUPLICATE_SAME_ACCESS);  /* Options */        }        /* Create the blocking IO semaphore */        thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);        if (thread->md.blocked_sema == NULL) {            return PR_FAILURE;        }		if (_native_threads_only) {			/* Create the blocking IO semaphore */			thread->md.thr_event = CreateEvent(NULL, TRUE, FALSE, NULL);			if (thread->md.thr_event == NULL) {				return PR_FAILURE;			}		}    }    return PR_SUCCESS;}PRStatus _PR_MD_CREATE_THREAD(PRThread *thread,                   void (*start)(void *),                   PRThreadPriority priority,                   PRThreadScope scope,                   PRThreadState state,                   PRUint32 stackSize){#if 0    thread->md.handle = CreateThread(                    NULL,                             /* security attrib */                    thread->stack->stackSize,         /* stack size      */                    (LPTHREAD_START_ROUTINE)start,    /* startup routine */                    (void *)thread,                   /* thread param    */                    CREATE_SUSPENDED,                 /* create flags    */                    &(thread->id) );                  /* thread id       */#else    thread->md.handle = (HANDLE) _beginthreadex(                    NULL,                    thread->stack->stackSize,                    (unsigned (__stdcall *)(void *))start,                    (void *)thread,                    CREATE_SUSPENDED,                    &(thread->id));#endif    if(!thread->md.handle) {        PRErrorCode prerror;        thread->md.fiber_last_error = GetLastError();        switch (errno) {            case ENOMEM:                prerror = PR_OUT_OF_MEMORY_ERROR;                break;            case EAGAIN:                prerror = PR_INSUFFICIENT_RESOURCES_ERROR;                break;            case EINVAL:                prerror = PR_INVALID_ARGUMENT_ERROR;                break;            default:                prerror = PR_UNKNOWN_ERROR;        }        PR_SetError(prerror, errno);        return PR_FAILURE;    }    thread->md.id = thread->id;    /*     * On windows, a thread is created with a thread priority of     * THREAD_PRIORITY_NORMAL.     */    if (priority != PR_PRIORITY_NORMAL) {        _PR_MD_SET_PRIORITY(&(thread->md), priority);    }    /* Activate the thread */    if ( ResumeThread( thread->md.handle ) != -1)        return PR_SUCCESS;    PR_SetError(PR_UNKNOWN_ERROR, GetLastError());    return PR_FAILURE;}void_PR_MD_JOIN_THREAD(_MDThread *md){    DWORD rv;    rv = WaitForSingleObject(md->handle, INFINITE);    PR_ASSERT(WAIT_OBJECT_0 == rv);}void_PR_MD_END_THREAD(void){    _endthreadex(0);}void    _PR_MD_YIELD(void){    /* Can NT really yield at all? */    Sleep(0);}void     _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri){

⌨️ 快捷键说明

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