Back to index

lightning-sunbird  0.9+nobinonly
w95thred.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "primpl.h"
00039 #include <process.h>  /* for _beginthreadex() */
00040 
00041 /* --- globals ------------------------------------------------ */
00042 #ifdef _PR_USE_STATIC_TLS
00043 __declspec(thread) struct PRThread  *_pr_thread_last_run;
00044 __declspec(thread) struct PRThread  *_pr_currentThread;
00045 __declspec(thread) struct _PRCPU    *_pr_currentCPU;
00046 #else
00047 DWORD _pr_currentThreadIndex;
00048 DWORD _pr_lastThreadIndex;
00049 DWORD _pr_currentCPUIndex;
00050 #endif
00051 int                           _pr_intsOff = 0; 
00052 _PRInterruptTable             _pr_interruptTable[] = { { 0 } };
00053 
00054 void
00055 _PR_MD_EARLY_INIT()
00056 {
00057 #ifndef _PR_USE_STATIC_TLS
00058     _pr_currentThreadIndex = TlsAlloc();
00059     _pr_lastThreadIndex = TlsAlloc();
00060     _pr_currentCPUIndex = TlsAlloc();
00061 #endif
00062 }
00063 
00064 void _PR_MD_CLEANUP_BEFORE_EXIT(void)
00065 {
00066     _PR_NT_FreeSids();
00067 
00068     _PR_MD_CleanupSockets();
00069 
00070     WSACleanup();
00071 
00072 #ifndef _PR_USE_STATIC_TLS
00073     TlsFree(_pr_currentThreadIndex);
00074     TlsFree(_pr_lastThreadIndex);
00075     TlsFree(_pr_currentCPUIndex);
00076 #endif
00077 }
00078 
00079 PRStatus
00080 _PR_MD_INIT_THREAD(PRThread *thread)
00081 {
00082     if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
00083         /*
00084         ** Warning:
00085         ** --------
00086         ** NSPR requires a real handle to every thread.
00087         ** GetCurrentThread() returns a pseudo-handle which
00088         ** is not suitable for some thread operations (e.g.,
00089         ** suspending).  Therefore, get a real handle from
00090         ** the pseudo handle via DuplicateHandle(...)
00091         */
00092         DuplicateHandle(
00093                 GetCurrentProcess(),     /* Process of source handle */
00094                 GetCurrentThread(),      /* Pseudo Handle to dup */
00095                 GetCurrentProcess(),     /* Process of handle */
00096                 &(thread->md.handle),    /* resulting handle */
00097                 0L,                      /* access flags */
00098                 FALSE,                   /* Inheritable */
00099                 DUPLICATE_SAME_ACCESS);  /* Options */
00100     }
00101 
00102     /* Create the blocking IO semaphore */
00103     thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);
00104     if (thread->md.blocked_sema == NULL)
00105         return PR_FAILURE;
00106        else
00107               return PR_SUCCESS;
00108 }
00109 
00110 static unsigned __stdcall
00111 pr_root(void *arg)
00112 {
00113     PRThread *thread = (PRThread *)arg;
00114     thread->md.start(thread);
00115     return 0;
00116 }
00117 
00118 PRStatus 
00119 _PR_MD_CREATE_THREAD(PRThread *thread, 
00120                   void (*start)(void *), 
00121                   PRThreadPriority priority, 
00122                   PRThreadScope scope, 
00123                   PRThreadState state, 
00124                   PRUint32 stackSize)
00125 {
00126 
00127     thread->md.start = start;
00128     thread->md.handle = (HANDLE) _beginthreadex(
00129                     NULL,
00130                     thread->stack->stackSize,
00131                     pr_root,
00132                     (void *)thread,
00133                     CREATE_SUSPENDED,
00134                     &(thread->id));
00135     if(!thread->md.handle) {
00136         return PR_FAILURE;
00137     }
00138 
00139     thread->md.id = thread->id;
00140     /*
00141      * On windows, a thread is created with a thread priority of
00142      * THREAD_PRIORITY_NORMAL.
00143      */
00144     if (priority != PR_PRIORITY_NORMAL) {
00145         _PR_MD_SET_PRIORITY(&(thread->md), priority);
00146     }
00147 
00148     /* Activate the thread */
00149     if ( ResumeThread( thread->md.handle ) != -1)
00150         return PR_SUCCESS;
00151 
00152     return PR_FAILURE;
00153 }
00154 
00155 void    
00156 _PR_MD_YIELD(void)
00157 {
00158     /* Can NT really yield at all? */
00159     Sleep(0);
00160 }
00161 
00162 void     
00163 _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
00164 {
00165     int nativePri;
00166     BOOL rv;
00167 
00168     if (newPri < PR_PRIORITY_FIRST) {
00169         newPri = PR_PRIORITY_FIRST;
00170     } else if (newPri > PR_PRIORITY_LAST) {
00171         newPri = PR_PRIORITY_LAST;
00172     }
00173     switch (newPri) {
00174         case PR_PRIORITY_LOW:
00175             nativePri = THREAD_PRIORITY_BELOW_NORMAL;
00176             break;
00177         case PR_PRIORITY_NORMAL:
00178             nativePri = THREAD_PRIORITY_NORMAL;
00179             break;
00180         case PR_PRIORITY_HIGH:
00181             nativePri = THREAD_PRIORITY_ABOVE_NORMAL;
00182             break;
00183         case PR_PRIORITY_URGENT:
00184             nativePri = THREAD_PRIORITY_HIGHEST;
00185     }
00186     rv = SetThreadPriority(thread->handle, nativePri);
00187     PR_ASSERT(rv);
00188     if (!rv) {
00189        PR_LOG(_pr_thread_lm, PR_LOG_MIN,
00190                 ("PR_SetThreadPriority: can't set thread priority\n"));
00191     }
00192     return;
00193 }
00194 
00195 void
00196 _PR_MD_CLEAN_THREAD(PRThread *thread)
00197 {
00198     BOOL rv;
00199 
00200     if (thread->md.blocked_sema) {
00201         rv = CloseHandle(thread->md.blocked_sema);
00202         PR_ASSERT(rv);
00203         thread->md.blocked_sema = 0;
00204     }
00205 
00206     if (thread->md.handle) {
00207         rv = CloseHandle(thread->md.handle);
00208         PR_ASSERT(rv);
00209         thread->md.handle = 0;
00210     }
00211 }
00212 
00213 void
00214 _PR_MD_EXIT_THREAD(PRThread *thread)
00215 {
00216     _PR_MD_CLEAN_THREAD(thread);
00217     _PR_MD_SET_CURRENT_THREAD(NULL);
00218 }
00219 
00220 
00221 void
00222 _PR_MD_EXIT(PRIntn status)
00223 {
00224     _exit(status);
00225 }
00226 
00227 PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
00228 {
00229     int rv;
00230 
00231     rv = SetThreadAffinityMask(thread->md.handle, mask);
00232 
00233     return rv?0:-1;
00234 }
00235 
00236 PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
00237 {
00238     PRInt32 rv, system_mask;
00239 
00240     rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
00241     
00242     return rv?0:-1;
00243 }
00244 
00245 void 
00246 _PR_MD_SUSPEND_CPU(_PRCPU *cpu) 
00247 {
00248     _PR_MD_SUSPEND_THREAD(cpu->thread);
00249 }
00250 
00251 void
00252 _PR_MD_RESUME_CPU(_PRCPU *cpu)
00253 {
00254     _PR_MD_RESUME_THREAD(cpu->thread);
00255 }
00256 
00257 void
00258 _PR_MD_SUSPEND_THREAD(PRThread *thread)
00259 {
00260     if (_PR_IS_NATIVE_THREAD(thread)) {
00261         DWORD previousSuspendCount;
00262         /* XXXMB - SuspendThread() is not a blocking call; how do we
00263          * know when the thread is *REALLY* suspended?
00264          */
00265         previousSuspendCount = SuspendThread(thread->md.handle);
00266         PR_ASSERT(previousSuspendCount == 0);
00267     }
00268 }
00269 
00270 void
00271 _PR_MD_RESUME_THREAD(PRThread *thread)
00272 {
00273     if (_PR_IS_NATIVE_THREAD(thread)) {
00274         DWORD previousSuspendCount;
00275         previousSuspendCount = ResumeThread(thread->md.handle);
00276         PR_ASSERT(previousSuspendCount == 1);
00277     }
00278 }
00279 
00280 PRThread*
00281 _MD_CURRENT_THREAD(void)
00282 {
00283 PRThread *thread;
00284 
00285        thread = _MD_GET_ATTACHED_THREAD();
00286 
00287        if (NULL == thread) {
00288               thread = _PRI_AttachThread(
00289             PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
00290        }
00291        PR_ASSERT(thread != NULL);
00292        return thread;
00293 }