source: trunk/libc/include/InnoTekLIBC/thread.h@ 2739

Last change on this file since 2739 was 2739, checked in by bird, 19 years ago

Started backend cleanup for portability. Work in progress.

  • Property cvs2svn:cvs-rev set to 1.14
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.0 KB
Line 
1/* $Id: thread.h 2739 2006-07-23 05:23:46Z bird $ */
2/** @file
3 *
4 * LIBC Thread Handling.
5 *
6 * Copyright (c) 2004-2006 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of InnoTek LIBC.
10 *
11 * InnoTek LIBC is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * InnoTek LIBC is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with InnoTek LIBC; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#ifndef __InnoTekLIBC_thread_h__
28#define __InnoTekLIBC_thread_h__
29
30/*******************************************************************************
31* Defined Constants And Macros *
32*******************************************************************************/
33/** Maximum number of TLS variables supported by LIBC.
34 * The current limit (128) is higher than for instance WinNT. But if
35 * you think we're wasting space, look at the page padding of the thread
36 * structure... */
37#define __LIBC_TLS_MAX 128
38
39
40/*******************************************************************************
41* Header Files *
42*******************************************************************************/
43#include <sys/cdefs.h>
44#include <time.h> /* struct tm; */
45#include <signal.h>
46#ifdef __NT__
47# include <klibc/nt/fib.h>
48#endif
49
50
51/*******************************************************************************
52* Structures and Typedefs *
53*******************************************************************************/
54struct _uheap;
55
56/**
57 * sigwait,sigwaitinfo, sigtimedwait data.
58 */
59typedef volatile struct __libc_thread_sigwait
60{
61 /** Done waitin' indicator.*/
62 volatile int fDone;
63 /** The signals we're waiting for. */
64 sigset_t SigSetWait;
65 /** The where to return signal info. */
66 siginfo_t SigInfo;
67} __LIBC_THREAD_SIGWAIT, *__LIBC_PTHREAD_SIGWAIT;
68
69
70/**
71 * sigsuspend data.
72 */
73typedef volatile struct __libc_thread_sigsuspend
74{
75 /** Done waitin' indicator.*/
76 volatile int fDone;
77} __LIBC_THREAD_SIGSUSPEND, *__LIBC_PTHREAD_SIGSUSPEND;
78
79
80/**
81 * Signal notification callback function.
82 *
83 * This is a notification which can be used to correct the state of
84 * a system object before any user code is executed.
85 *
86 * The semaphore lock is hold and signals are all on hold, so be very careful with waitin
87 * on other semphores and stuff like that. Crashing is totally forbidden. :-)
88 *
89 * @param iSignalNo The signal number.
90 * @param pvUser The user argument.
91 */
92typedef void __LIBC_FNSIGCALLBACK(int iSignalNo, void *pvUser);
93/** Pointer to a signal callback function. */
94typedef __LIBC_FNSIGCALLBACK *__LIBC_PFNSIGCALLBACK;
95
96
97/**
98 * Per thread structure for LIBC.
99 *
100 * This structure contains buffers and variables which in a single threaded
101 * LIBC would be static.
102 *
103 * Members most frequently used have been put together at the front.
104 */
105typedef struct __libc_thread
106{
107 /** errno value. (Comes first, see errnofun.s.) */
108 int iErrNo;
109 /** Default tiled heap. */
110 struct _uheap * pTiledHeap;
111 /** Default regular heap. */
112 struct _uheap * pRegularHeap;
113 /** Reference count. */
114 volatile unsigned cRefs;
115 /** Thread Id. */
116 unsigned tid;
117 /** Pointer to next thread in the list. */
118 struct __libc_thread *pNext;
119 /** New TLS variable array. */
120 void *apvTLS[__LIBC_TLS_MAX];
121 /** Old TLS variable. */
122 void *pvThreadStoreVar;
123
124 /** The nesting depth of the default logger. */
125 unsigned cDefLoggerDepth;
126 /** Buffer used by asctime() and indirectly by ctime() . (Adds two 2 bytes for padding). */
127 char szAscTimeAndCTimeBuf[26+2];
128 /** Buffer used by gmtime() and localtime(). */
129 struct tm GmTimeAndLocalTimeBuf;
130 /** Buffer used by tmpnam(). */
131 char szTmpNamBuf[16];
132 /** Current posistion of strtok(). */
133 char *pszStrTokPos;
134 /** Buffer used by strerror() to format unknown error values. */
135 char szStrErrorBuf[28];
136 /** Buffer used by _getvol(). */
137 char szVolLabelBuf[12];
138 /** Buffer used by ttyname(). */
139 char szTTYNameBuf[32];
140
141 /** Pending signals.
142 * Protected by the signal semaphore. */
143 sigset_t SigSetPending;
144 /** Blocked signals.
145 * Protected by the signal semaphore. */
146 sigset_t SigSetBlocked;
147 /** Old Blocked signals. Used by sigsuspend().
148 * sigsuspend() sets this and fSigSetBlockedOld. When a signal is to be
149 * delivered this member will be pushed on the stack for use on an eventual
150 * return. fSigSetBlockOld will be clared.
151 * Protected by the signal semaphore. */
152 sigset_t SigSetBlockedOld;
153
154 /** Signals queued for delivery on this thread.
155 * Protected by the signal semaphore. */
156 struct
157 {
158 struct SignalQueued *pHead;
159 struct SignalQueued *pTail;
160 } SigQueue;
161
162 /** Alternate signal stack block address.
163 * Protected by the signal semaphore. */
164 void *pvSigStack;
165 /** Alternate signal stack block size.
166 * Protected by the signal semaphore. */
167 size_t cbSigStack;
168
169 /** @defgroup libc_threadstruct_flags Thread Flags
170 * @todo checkup access safety here!
171 * @{ */
172 /** If set SigSetBlockedOld should be used used to restore SigSetBlocked
173 * when returning from a signal handler. */
174 unsigned fSigSetBlockedOld : 1;
175 /** If set the stack block pointed to by pvSigStack is in use. */
176 unsigned fSigStackActive : 1;
177 /** If set the thread is internal.
178 * This means the thread will not receive signals. */
179 unsigned fInternalThread : 1;
180 /** @} */
181
182 /** Flags whether or not the thread is being forced to evaluate its
183 * pending signals.
184 *
185 * All updates of this variable must be done atomically and when owning
186 * the signal semaphore. The atomically requirement is because it's being
187 * read without owning the semaphore.
188 */
189 volatile unsigned fSigBeingPoked;
190
191 /** The millisecond timestamp of the last signal.
192 * This is used to detect system call interruptions (select). The function will clear
193 * before doing the system call and evaluate it when the call returns. signals.c will set it
194 * when ever a thread enters for processing a signal asynchronously. */
195 volatile unsigned long ulSigLastTS;
196 /** Callback on signal/exception. */
197 __LIBC_PFNSIGCALLBACK pfnSigCallback;
198 /** User argument to signal/exception callback. */
199 void *pvSigCallbackUser;
200
201 /** Thread status, chiefly used for the u member of the thread structure. */
202 volatile enum enmLIBCThreadStatus
203 {
204 /** The thread status must be queried from the OS. */
205 enmLIBCThreadStatus_unknown = 0,
206 /** The thread status must be queried from the OS. */
207 enmLIBCThreadStatus_startup,
208 /** The thread is in a sigwait(), sigwaitinfo(), or sigtimedwait() call. */
209 enmLIBCThreadStatus_sigwait,
210 /** The thread is in a sigsuspend() call. */
211 enmLIBCThreadStatus_sigsuspend,
212 } enmStatus;
213
214 /** Data used in certain thread states.
215 * Use the enmStatus field to determin which way to read the data items here.
216 */
217 union
218 {
219 /** enmLIBCThreadStatus_startup: Begin Thread Arguments. */
220 struct __libc_thread_u_startup
221 {
222 /** Thread argument. */
223 void *pvArg;
224 /** Thread routine. */
225 void (*pfnStart)(void *pvArg);
226 } startup;
227
228 /** enmLIBCThreadStatus_sigwait: Thread blocked in sigwait(), sigwaitinfo() or sigtimedwait(). */
229 __LIBC_PTHREAD_SIGWAIT pSigWait;
230 /** enmLIBCThreadStatus_sigsuspend: Thread blocked in sigsuspend(). */
231 __LIBC_PTHREAD_SIGSUSPEND pSigSuspend;
232 } u;
233
234 /** Data used by the backends. */
235 union __libc_backend_data
236 {
237 struct __libc_sys
238 {
239 /** Directory find data entry.
240 * Used by __findfirst() and __findnext(). */
241 struct find_data
242 {
243 /** Directory handle. HDIR_CREATE if no session opened. */
244 unsigned long hdir;
245 /** Type of buffer content. FIL_STANDARDL or FIL_STANDARD,
246 * i.e. FILEFINDBUF4 or FILEFINDBUF4L. */
247 unsigned long fType;
248 /** Number of files left in the buffer. */
249 unsigned long cFiles;
250 /** Pointer to the next entry. Don't test on this, test on cFiles! */
251 const char *pchNext;
252 /** Buffer. */
253 char achBuffer[2048];
254 } fd;
255 } sys;
256 } b;
257
258
259} __LIBC_THREAD;
260
261
262#ifndef __LIBC_THREAD_DECLARED
263#define __LIBC_THREAD_DECLARED
264typedef struct __libc_thread *__LIBC_PTHREAD, **__LIBC_PPTHREAD;
265#endif
266
267
268/**
269 * Thread Termination Callback Registration Record. (cool name, right)
270 * For use with __libc_ThreadRegisterTermCallback().
271 */
272typedef struct __libc_ThreadTermCbRegRec
273{
274 /** This member must be initialized to NULL. */
275 struct __libc_ThreadTermCbRegRec *pNext;
276 /** Flags field reserved for future use.
277 * Must be initalized to ZERO. */
278 unsigned fFlags;
279 /**
280 * The callback function.
281 *
282 * @param pRegRec Registration record which the callback was registered with.
283 * @param fFlags Reserved for future use. Will always be zero when fFlags
284 * in the RegRec is zero.
285 */
286 void (*pfnCallback)(struct __libc_ThreadTermCbRegRec *pRegRec, unsigned fFlags);
287} __LIBC_THREADTERMCBREGREC, *__LIBC_PTHREADTERMCBREGREC;
288
289
290/*******************************************************************************
291* Global Variables *
292*******************************************************************************/
293__BEGIN_DECLS
294#ifdef __OS2__
295/** Pointer to the TLS ULONG (OS/2 rules) which will point to the LIBC thread
296 * structure for the current thread.
297 * The TLS ULONG is allocated by __init_dll(). The thread structure it points to
298 * is allocated on demand. */
299extern __LIBC_PPTHREAD __libc_gpTLS;
300#endif /* __OS2__ */
301__END_DECLS
302
303
304/*******************************************************************************
305* External Functions *
306*******************************************************************************/
307__BEGIN_DECLS
308
309
310/**
311 * Get the thread structure for the current thread.
312 *
313 * Used by the __libc_threadCurrent() macro for allocating a thread structure for the
314 * current thread when such doesn't exist.
315 *
316 * @returns pointer to current thread struct.
317 *
318 * @remark No reference counting here, the current thread have a permanent
319 * reference to it self.
320 * @remark This API is considered to be internal to LIBC and is thus not
321 * exposed in the shared library version of LIBC. Please don't call it.
322 * External LIBs should use the __libc_TLS*() API.
323 */
324__LIBC_PTHREAD __libc_threadCurrentSlow(void);
325
326/**
327 * Get the thread structure for the current thread.
328 *
329 * Do not create anything automatically.
330 *
331 * @returns pointer to current thread struct.
332 * @returns NULL if not initiated.
333 *
334 * @remark No reference counting here, current thread have a permanent
335 * reference to it self.
336 * @remark This API is considered to be internal to LIBC and is thus not
337 * exposed in the shared library version of LIBC. Please don't call it.
338 * External LIBs should use the __libc_TLS*() API.
339 */
340#ifdef __OS2__
341# define __libc_threadCurrentNoAuto() (__libc_gpTLS ? *__libc_gpTLS : NULL)
342#elif defined(__NT__)
343# define __libc_threadCurrentNoAuto() (fibGetLibcThread())
344#else
345# error "Port me!"
346#endif
347
348/**
349 * Get the thread structure for the current thread.
350 *
351 * Will automatically allocate a thread structure if such is not yet done
352 * for the thread.
353 *
354 * @returns pointer to current thread struct.
355 *
356 * @remark No reference counting here, the current thread have a permanent
357 * reference to it self.
358 * @remark This API is considered to be internal to LIBC and is thus not
359 * exposed in the shared library version of LIBC. Please don't call it.
360 * External LIBs should use the __libc_TLS*() API.
361 */
362static __inline__ __LIBC_PTHREAD __libc_threadCurrent(void)
363{
364#ifdef __OS2__
365 __LIBC_PTHREAD pThread = *__libc_gpTLS;
366#else
367 __LIBC_PTHREAD pThread = __libc_threadCurrentNoAuto();
368#endif
369 if (__predict_true(pThread != (__LIBC_PTHREAD)0))
370 return pThread;
371 return __libc_threadCurrentSlow();
372}
373
374/**
375 * Get the thread structure for the thread specified by it's thread identification.
376 *
377 * Used for instance by signal handling to change the signal properties of another
378 * thread.
379 *
380 * @returns Pointer to threads thread struct.
381 * The caller _must_ call __libc_threadRelease() when it's done using the
382 * thread structure.
383 * @returns NULL if the thread wasn't found.
384 * @param tid The Thread Id of the thread to find.
385 * @remark This API is considered to be internal to LIBC and is thus not
386 * exposed in the shared library version of LIBC. Please don't call it.
387 */
388__LIBC_PTHREAD __libc_threadLookup(unsigned tid);
389
390
391/**
392 * Get the thread structure for a thread selected by a custom callback function.
393 *
394 * @returns Pointer to the selected thread.
395 * The caller _must_ call __libc_threadRelease() when it's done using the
396 * thread structure.
397 * @param pfnCallback Function which will to the thread selection.
398 *
399 * Returns 1 if the current thread should be returned.
400 * Returns 2 if the current thread should be returned immediately.
401 * Returns 0 if the current best thread should remain unchanged.
402 * Returns -1 if the enumeration should fail (immediately).
403 *
404 * pCur The current thread.
405 * pBest The current best thread.
406 * pvParam User parameter.
407 *
408 * @param pvParam User Parameter.
409 */
410__LIBC_PTHREAD __libc_threadLookup2(int (pfnCallback)(__LIBC_PTHREAD pCur, __LIBC_PTHREAD pBest, void *pvParam), void *pvParam);
411
412
413/**
414 * Enumerates all the threads LIBC is aware of subjecting each of them to a
415 * caller specified callback function.
416 *
417 * @returns 0 on success.
418 * @returns -1 if pfnCallback returned -1.
419 *
420 * @param pfnCallback Function which will to the thread selection.
421 *
422 * Returns 0 if the enmeration should continue.
423 * Returns -1 if the enumeration should fail (immediately).
424 *
425 * pCur The current thread.
426 * pvParam User parameter.
427 *
428 * @param pvParam User Parameter.
429 */
430int __libc_threadEnum(int (pfnCallback)(__LIBC_PTHREAD pCur, void *pvParam), void *pvParam);
431
432
433/**
434 * Allocate and initialize a thread structure for a thread which is yet
435 * to be created.
436 *
437 * The returned thread structure will have cRefs set to 1, thus
438 * use __libc_threadDereference() to free it.
439 *
440 * @returns Pointer to thread structure.
441 * @returns NULL on error. errno set.
442 */
443__LIBC_PTHREAD __libc_threadAlloc(void);
444
445
446/**
447 * Sets up the current thread to use the thread structure pThrd.
448 *
449 * @param pThrd Pointer to the thread structure this thread
450 * should be using.
451 */
452void __libc_threadUse(__LIBC_PTHREAD pThrd);
453
454
455/**
456 * Dereferences a thread structure referenced by __libc_threadLookup() or
457 * __libc_threadLookup2(), or allocated by __libc_threadAlloc().
458 *
459 * LIBC maintains reference counting on the thread structure so the thread
460 * structure will not be freed by the thread it represent while someone else
461 * is accessing it. However, the reference counting does not protect any of
462 * the structures members from writes or reads, that's left to the users of
463 * the members to synchronize between them.
464 *
465 * @returns pointer to threads thread struct.
466 * @returns NULL if the thread wasn't found.
467 * @param pThrd Pointer to thread structure returned by __libc_threadLookup(),
468 * __libc_threadLookup2() or __libc_threadAlloc().
469 * @remark This API is considered to be internal to LIBC and is thus not
470 * exposed in the shared library version of LIBC. Please don't call it.
471 */
472void __libc_threadDereference(__LIBC_PTHREAD pThrd);
473
474
475/**
476 * Register a thread destruction callback.
477 *
478 * This will be called when one thread is terminating normally, i.e. calling
479 * _endthread() or returning from it's thread function.
480 * When LIBC implements pthreads basics any new non-abnormal thread exit will
481 * cause a callback too.
482 *
483 * @param pRegRec Pointer to thread registration record.
484 * This must be initialized as described in the documation of
485 * the structure. After calling this API the memory must not
486 * be touched or freed by the application. It is not possible
487 * to unregister a callback at present.
488 *
489 * @remark We might wanna extend the API at a later point for calling back
490 * at abnormal termination and such. Such extensions will be done
491 * using the fFlags member of __LIBC_THREADTERMCBREGREC and the fFlags
492 * parameter to the callback.
493 */
494int __libc_ThreadRegisterTermCallback(__LIBC_PTHREADTERMCBREGREC pRegRec);
495
496/**
497 * Internal API which is called by a thread exit to work the registered callbacks.
498 *
499 * Not called for thread 1.
500 *
501 * @param fFlags Reserved for termination reasons.
502 * Zero means normal exit, no other codes have been defined.
503 */
504void __libc_threadTermination(unsigned fFlags);
505
506
507/** @group InnoTek LIBC Thread Local Storage
508 * @{
509 */
510
511/**
512 * Allocates a TLS entry.
513 *
514 * @returns index of the allocated TLS index.
515 * @returns -1 on failure. errno set.
516 */
517int __libc_TLSAlloc(void);
518
519/**
520 * Frees a TLS entry allocated by __libc_TLSAlloc().
521 *
522 * @returns 0 on success.
523 * @returns -1 on failure. errno set.
524 * @param iIndex Value returned by __libc_TLSAlloc().
525 */
526int __libc_TLSFree(int iIndex);
527
528/**
529 * Get the value stored in an allocated TLS entry.
530 *
531 * @returns value in given TLS entry.
532 * @returns NULL on failure with errno set.
533 * @param iIndex Value returned by __libc_TLSAlloc().
534 */
535void * __libc_TLSGet(int iIndex);
536
537/**
538 * Set the value stored in an allocated TLS entry.
539 *
540 * @returns 0 on success.
541 * @returns -1 on failure. errno set.
542 * @param iIndex Value returned by __libc_TLSAlloc().
543 * @param pvValue Value to store.
544 */
545int __libc_TLSSet(int iIndex, void *pvValue);
546
547/**
548 * Register a thread termination destructor for an TLS entry.
549 *
550 * The destructor function will be called when a thread terminates
551 * in a normal fashion and the TLS entry iIndex of that thread is
552 * not NULL.
553 *
554 * There will be no callbacks in thread 1.
555 *
556 * @returns 0 on succces.
557 * @returns -1 on failure. errno set.
558 * @param iIndex Value returned by __libc_TLSAlloc().
559 * @param pfnDestructor Callback function. Use NULL to unregister a previously
560 * registered destructor.
561 *
562 * It's pvValue argument is the non-zero value in the
563 * TLS entry for the thread it's called on.
564 *
565 * It's fFlags argument is reserved for future use, it will
566 * always be zero when the fFlags parameter to this API is zero.
567 *
568 * @param fFlags Flags reserved for future use. At the moment
569 * only ZERO is allowed.
570 *
571 * @remark The application is not allowed to call __libc_TLSFree() for iIndex when calling
572 * this function. The result from doing that is undefined.
573 */
574int __libc_TLSDestructor(int iIndex, void (*pfnDestructor)(void *pvValue, int iIndex, unsigned fFlags), unsigned fFlags);
575
576
577/**
578 * Get pointer to the destructor function registered for the given TLS entry.
579 *
580 * @returns NULL if invalid entry, errno set.
581 * @returns NULL if no entry registered.
582 * @returns Pointer to destructor if registered.
583 *
584 * @param iIndex Value returned by __libc_TLSAlloc().
585 * @param pfFlags Where to store the flags supplied to __libc_TLSDestructor().
586 * NULL is ok.
587 */
588void (*__libc_TLSGetDestructor(int iIndex, unsigned *pfFlags))(void *, int, unsigned);
589
590/* fix later */
591int __libc_back_threadCreate(void (*pfnStart)(void *), unsigned cbStack, void *pvArg, int fInternal);
592
593/** @} */
594
595__END_DECLS
596
597#endif
598
Note: See TracBrowser for help on using the repository browser.