-
Notifications
You must be signed in to change notification settings - Fork 0
/
pth_tcb.c
150 lines (130 loc) · 5.97 KB
/
pth_tcb.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
** GNU Pth - The GNU Portable Threads
** Copyright (c) 1999-2006 Ralf S. Engelschall <[email protected]>
**
** This file is part of GNU Pth, a non-preemptive thread scheduling
** library which can be found at http://www.gnu.org/software/pth/.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA, or contact Ralf S. Engelschall <[email protected]>.
**
** pth_tcb.c: Pth thread control block handling
*/
/* Patient: Doctor, it hurts when I do this!
Doctor: Well, then don't do it. */
#include "pth_p.h"
#if cpp
#define PTH_TCB_NAMELEN 40
/* thread control block */
struct pth_st {
/* priority queue handling */
pth_t q_next; /* next thread in pool */
pth_t q_prev; /* previous thread in pool */
int q_prio; /* (relative) priority of thread when queued */
/* standard thread control block ingredients */
int prio; /* base priority of thread */
char name[PTH_TCB_NAMELEN];/* name of thread (mainly for debugging) */
int dispatches; /* total number of thread dispatches */
pth_state_t state; /* current state indicator for thread */
/* timing */
pth_time_t spawned; /* time point at which thread was spawned */
pth_time_t lastran; /* time point at which thread was last running */
pth_time_t running; /* time range the thread was already running */
/* event handling */
pth_event_t events; /* events the tread is waiting for */
/* per-thread signal handling */
sigset_t sigpending; /* set of pending signals */
int sigpendcnt; /* number of pending signals */
/* machine context */
pth_mctx_t mctx; /* last saved machine state of thread */
char *stack; /* pointer to thread stack */
unsigned int stacksize; /* size of thread stack */
long *stackguard; /* stack overflow guard */
int stackloan; /* stack type */
void *(*start_func)(void *); /* start routine */
void *start_arg; /* start argument */
/* thread joining */
int joinable; /* whether thread is joinable */
void *join_arg; /* joining argument */
/* per-thread specific storage */
const void **data_value; /* thread specific values */
int data_count; /* number of stored values */
/* cancellation support */
int cancelreq; /* cancellation request is pending */
unsigned int cancelstate; /* cancellation state of thread */
pth_cleanup_t *cleanups; /* stack of thread cleanup handlers */
/* mutex ring */
pth_ring_t mutexring; /* ring of aquired mutex structures */
#ifdef PTH_EX
/* per-thread exception handling */
ex_ctx_t ex_ctx; /* exception handling context */
#endif
};
#endif /* cpp */
intern const char *pth_state_names[] = {
"scheduler", "new", "ready", "running", "waiting", "dead"
};
#if defined(MINSIGSTKSZ) && !defined(SIGSTKSZ)
#define SIGSTKSZ MINSIGSTKSZ
#endif
#if !defined(SIGSTKSZ)
#define SIGSTKSZ 8192
#endif
/* allocate a thread control block */
intern pth_t pth_tcb_alloc(unsigned int stacksize, void *stackaddr)
{
pth_t t;
if (stacksize > 0 && stacksize < SIGSTKSZ)
stacksize = SIGSTKSZ;
if ((t = (pth_t)malloc(sizeof(struct pth_st))) == NULL)
return NULL;
t->stacksize = stacksize;
t->stack = NULL;
t->stackguard = NULL;
t->stackloan = (stackaddr != NULL ? TRUE : FALSE);
if (stacksize > 0) { /* stacksize == 0 means "main" thread */
if (stackaddr != NULL)
t->stack = (char *)(stackaddr);
else {
if ((t->stack = (char *)malloc(stacksize)) == NULL) {
pth_shield { free(t); }
return NULL;
}
}
#if PTH_STACKGROWTH < 0
/* guard is at lowest address (alignment is guarrantied) */
t->stackguard = (long *)((long)t->stack); /* double cast to avoid alignment warning */
#else
/* guard is at highest address (be careful with alignment) */
t->stackguard = (long *)(t->stack+(((stacksize/sizeof(long))-1)*sizeof(long)));
#endif
*t->stackguard = 0xDEAD;
}
return t;
}
/* free a thread control block */
intern void pth_tcb_free(pth_t t)
{
if (t == NULL)
return;
if (t->stack != NULL && !t->stackloan)
free(t->stack);
if (t->data_value != NULL)
free(t->data_value);
if (t->cleanups != NULL)
pth_cleanup_popall(t, FALSE);
free(t);
return;
}