Home | History | Annotate | Download | only in nspr
      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /*
      3  * The contents of this file are subject to the Mozilla Public
      4  * License Version 1.1 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of
      6  * the License at http://www.mozilla.org/MPL/
      7  *
      8  * Software distributed under the License is distributed on an "AS
      9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     10  * implied. See the License for the specific language governing
     11  * rights and limitations under the License.
     12  *
     13  * The Original Code is the Netscape Portable Runtime (NSPR).
     14  *
     15  * The Initial Developer of the Original Code is Netscape
     16  * Communications Corporation.  Portions created by Netscape are
     17  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
     18  * Rights Reserved.
     19  *
     20  * Contributor(s):
     21  *
     22  * Alternatively, the contents of this file may be used under the
     23  * terms of the GNU General Public License Version 2 or later (the
     24  * "GPL"), in which case the provisions of the GPL are applicable
     25  * instead of those above.  If you wish to allow use of your
     26  * version of this file only under the terms of the GPL and not to
     27  * allow others to use your version of this file under the MPL,
     28  * indicate your decision by deleting the provisions above and
     29  * replace them with the notice and other provisions required by
     30  * the GPL.  If you do not delete the provisions above, a recipient
     31  * may use your version of this file under either the MPL or the
     32  * GPL.
     33  */
     34 
     35 #ifndef prthread_h___
     36 #define prthread_h___
     37 
     38 /*
     39 ** API for NSPR threads. On some architectures (MAC and WIN16
     40 ** notably) pre-emptibility is not guaranteed. Hard priority scheduling
     41 ** is not guaranteed, so programming using priority based synchronization
     42 ** is a no-no.
     43 **
     44 ** NSPR threads are scheduled based loosly on their client set priority.
     45 ** In general, a thread of a higher priority has a statistically better
     46 ** chance of running relative to threads of lower priority. However,
     47 ** NSPR uses multiple strategies to provide execution vehicles for thread
     48 ** abstraction of various host platforms. As it turns out, there is little
     49 ** NSPR can do to affect the scheduling attributes of "GLOBAL" threads.
     50 ** However, a semblance of GLOBAL threads is used to implement "LOCAL"
     51 ** threads. An arbitrary number of such LOCAL threads can be assigned to
     52 ** a single GLOBAL thread.
     53 **
     54 ** For scheduling, NSPR will attempt to run the highest priority LOCAL
     55 ** thread associated with a given GLOBAL thread. It is further assumed
     56 ** that the host OS will apply some form of "fair" scheduling on the
     57 ** GLOBAL threads.
     58 **
     59 ** Threads have a "system flag" which when set indicates the thread
     60 ** doesn't count for determining when the process should exit (the
     61 ** process exits when the last user thread exits).
     62 **
     63 ** Threads also have a "scope flag" which controls whether the threads
     64 ** are scheduled in the local scope or scheduled by the OS globally. This
     65 ** indicates whether a thread is permanently bound to a native OS thread.
     66 ** An unbound thread competes for scheduling resources in the same process.
     67 **
     68 ** Another flag is "state flag" which control whether the thread is joinable.
     69 ** It allows other threads to wait for the created thread to reach completion.
     70 **
     71 ** Threads can have "per-thread-data" attached to them. Each thread has a
     72 ** per-thread error number and error string which are updated when NSPR
     73 ** operations fail.
     74 */
     75 #include "prtypes.h"
     76 #include "prinrval.h"
     77 
     78 PR_BEGIN_EXTERN_C
     79 
     80 typedef struct PRThread PRThread;
     81 typedef struct PRThreadStack PRThreadStack;
     82 
     83 typedef enum PRThreadType {
     84     PR_USER_THREAD,
     85     PR_SYSTEM_THREAD
     86 } PRThreadType;
     87 
     88 typedef enum PRThreadScope {
     89     PR_LOCAL_THREAD,
     90     PR_GLOBAL_THREAD,
     91     PR_GLOBAL_BOUND_THREAD
     92 } PRThreadScope;
     93 
     94 typedef enum PRThreadState {
     95     PR_JOINABLE_THREAD,
     96     PR_UNJOINABLE_THREAD
     97 } PRThreadState;
     98 
     99 typedef enum PRThreadPriority
    100 {
    101     PR_PRIORITY_FIRST = 0,      /* just a placeholder */
    102     PR_PRIORITY_LOW = 0,        /* the lowest possible priority */
    103     PR_PRIORITY_NORMAL = 1,     /* most common expected priority */
    104     PR_PRIORITY_HIGH = 2,       /* slightly more aggressive scheduling */
    105     PR_PRIORITY_URGENT = 3,     /* it does little good to have more than one */
    106     PR_PRIORITY_LAST = 3        /* this is just a placeholder */
    107 } PRThreadPriority;
    108 
    109 /*
    110 ** Create a new thread:
    111 **     "type" is the type of thread to create
    112 **     "start(arg)" will be invoked as the threads "main"
    113 **     "priority" will be created thread's priority
    114 **     "scope" will specify whether the thread is local or global
    115 **     "state" will specify whether the thread is joinable or not
    116 **     "stackSize" the size of the stack, in bytes. The value can be zero
    117 **        and then a machine specific stack size will be chosen.
    118 **
    119 ** This can return NULL if some kind of error occurs, such as if memory is
    120 ** tight.
    121 **
    122 ** If you want the thread to start up waiting for the creator to do
    123 ** something, enter a lock before creating the thread and then have the
    124 ** threads start routine enter and exit the same lock. When you are ready
    125 ** for the thread to run, exit the lock.
    126 **
    127 ** If you want to detect the completion of the created thread, the thread
    128 ** should be created joinable.  Then, use PR_JoinThread to synchrnoize the
    129 ** termination of another thread.
    130 **
    131 ** When the start function returns the thread exits. If it is the last
    132 ** PR_USER_THREAD to exit then the process exits.
    133 */
    134 NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
    135                      void (PR_CALLBACK *start)(void *arg),
    136                      void *arg,
    137                      PRThreadPriority priority,
    138                      PRThreadScope scope,
    139                      PRThreadState state,
    140                      PRUint32 stackSize);
    141 
    142 /*
    143 ** Wait for thread termination:
    144 **     "thread" is the target thread
    145 **
    146 ** This can return PR_FAILURE if no joinable thread could be found
    147 ** corresponding to the specified target thread.
    148 **
    149 ** The calling thread is blocked until the target thread completes.
    150 ** Several threads cannot wait for the same thread to complete; one thread
    151 ** will operate successfully and others will terminate with an error PR_FAILURE.
    152 ** The calling thread will not be blocked if the target thread has already
    153 ** terminated.
    154 */
    155 NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
    156 
    157 /*
    158 ** Return the current thread object for the currently running code.
    159 ** Never returns NULL.
    160 */
    161 NSPR_API(PRThread*) PR_GetCurrentThread(void);
    162 #ifndef NO_NSPR_10_SUPPORT
    163 #define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
    164 #endif /* NO_NSPR_10_SUPPORT */
    165 
    166 /*
    167 ** Get the priority of "thread".
    168 */
    169 NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
    170 
    171 /*
    172 ** Change the priority of the "thread" to "priority".
    173 */
    174 NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
    175 
    176 /*
    177 ** This routine returns a new index for per-thread-private data table.
    178 ** The index is visible to all threads within a process. This index can
    179 ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
    180 ** to save and retrieve data associated with the index for a thread.
    181 **
    182 ** Each index is associationed with a destructor function ('dtor'). The function
    183 ** may be specified as NULL when the index is created. If it is not NULL, the
    184 ** function will be called when:
    185 **      - the thread exits and the private data for the associated index
    186 **        is not NULL,
    187 **      - new thread private data is set and the current private data is
    188 **        not NULL.
    189 **
    190 ** The index independently maintains specific values for each binding thread.
    191 ** A thread can only get access to its own thread-specific-data.
    192 **
    193 ** Upon a new index return the value associated with the index for all threads
    194 ** is NULL, and upon thread creation the value associated with all indices for
    195 ** that thread is NULL.
    196 **
    197 ** Returns PR_FAILURE if the total number of indices will exceed the maximun
    198 ** allowed.
    199 */
    200 typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
    201 
    202 NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
    203     PRUintn *newIndex, PRThreadPrivateDTOR destructor);
    204 
    205 /*
    206 ** Define some per-thread-private data.
    207 **     "tpdIndex" is an index into the per-thread private data table
    208 **     "priv" is the per-thread-private data
    209 **
    210 ** If the per-thread private data table has a previously registered
    211 ** destructor function and a non-NULL per-thread-private data value,
    212 ** the destructor function is invoked.
    213 **
    214 ** This can return PR_FAILURE if the index is invalid.
    215 */
    216 NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
    217 
    218 /*
    219 ** Recover the per-thread-private data for the current thread. "tpdIndex" is
    220 ** the index into the per-thread private data table.
    221 **
    222 ** The returned value may be NULL which is indistinguishable from an error
    223 ** condition.
    224 **
    225 ** A thread can only get access to its own thread-specific-data.
    226 */
    227 NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
    228 
    229 /*
    230 ** This routine sets the interrupt request for a target thread. The interrupt
    231 ** request remains in the thread's state until it is delivered exactly once
    232 ** or explicitly canceled.
    233 **
    234 ** A thread that has been interrupted will fail all NSPR blocking operations
    235 ** that return a PRStatus (I/O, waiting on a condition, etc).
    236 **
    237 ** PR_Interrupt may itself fail if the target thread is invalid.
    238 */
    239 NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
    240 
    241 /*
    242 ** Clear the interrupt request for the calling thread. If no such request
    243 ** is pending, this operation is a noop.
    244 */
    245 NSPR_API(void) PR_ClearInterrupt(void);
    246 
    247 /*
    248 ** Block the interrupt for the calling thread.
    249 */
    250 NSPR_API(void) PR_BlockInterrupt(void);
    251 
    252 /*
    253 ** Unblock the interrupt for the calling thread.
    254 */
    255 NSPR_API(void) PR_UnblockInterrupt(void);
    256 
    257 /*
    258 ** Make the current thread sleep until "ticks" time amount of time
    259 ** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
    260 ** equivalent to calling PR_Yield. Calling PR_Sleep with an argument
    261 ** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result
    262 ** in a PR_FAILURE error return.
    263 */
    264 NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
    265 
    266 /*
    267 ** Get the scoping of this thread.
    268 */
    269 NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
    270 
    271 /*
    272 ** Get the type of this thread.
    273 */
    274 NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
    275 
    276 /*
    277 ** Get the join state of this thread.
    278 */
    279 NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
    280 
    281 PR_END_EXTERN_C
    282 
    283 #endif /* prthread_h___ */
    284