initial load of upstream version 1.06.32
[xmlrpc-c] / lib / abyss / src / thread_pthread.c
1 #include <unistd.h>
2 #include <pthread.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <signal.h>
6
7 #include "xmlrpc_config.h"
8
9 #include "mallocvar.h"
10 #include "xmlrpc-c/string_int.h"
11
12 #include "xmlrpc-c/abyss.h"
13
14 #include "thread.h"
15
16
17
18 struct abyss_thread {
19     pthread_t       thread;
20     void *          userHandle;
21     TThreadProc *   func;
22     TThreadDoneFn * threadDone;
23 };
24
25 /* We used to have THREAD_STACK_SIZE = 16K, which was said to be the
26    minimum stack size on Win32.  Scott Kolodzeski found in November
27    2005 that this was insufficient for 64 bit Solaris -- we fail
28    when creating the first thread.  So we changed to 128K.
29 */
30 #define  THREAD_STACK_SIZE (128*1024L)
31
32
33 typedef void * (pthreadStartRoutine)(void *);
34
35
36
37 static pthreadStartRoutine pthreadStart;
38
39 static void *
40 pthreadStart(void * const arg) {
41
42     struct abyss_thread * const threadP = arg;
43     abyss_bool const executeTrue = true;
44
45     pthread_cleanup_push(threadP->threadDone, threadP->userHandle);
46
47     threadP->func(threadP->userHandle);
48
49     pthread_cleanup_pop(executeTrue);
50
51     return NULL;
52 }
53
54
55
56 void
57 ThreadCreate(TThread **      const threadPP,
58              void *          const userHandle,
59              TThreadProc   * const func,
60              TThreadDoneFn * const threadDone,
61              abyss_bool      const useSigchld ATTR_UNUSED,
62              const char **   const errorP) {
63
64     TThread * threadP;
65
66     MALLOCVAR(threadP);
67     if (threadP == NULL)
68         xmlrpc_asprintf(errorP,
69                         "Can't allocate memory for thread descriptor.");
70     else {
71         pthread_attr_t attr;
72         int rc;
73
74         pthread_attr_init(&attr);
75
76         pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
77         
78         threadP->userHandle = userHandle;
79         threadP->func       = func;
80         threadP->threadDone = threadDone;
81
82         rc = pthread_create(&threadP->thread, &attr,
83                             pthreadStart, threadP);
84         if (rc == 0) {
85             *errorP = NULL;
86             *threadPP = threadP;
87         } else
88             xmlrpc_asprintf(
89                 errorP, "pthread_create() failed, errno = %d (%s)",
90                 errno, strerror(errno));
91         
92         pthread_attr_destroy(&attr);
93
94         if (*errorP)
95             free(threadP);
96     }
97 }
98
99
100
101 abyss_bool
102 ThreadRun(TThread * const threadP ATTR_UNUSED) {
103     return TRUE;    
104 }
105
106
107
108 abyss_bool
109 ThreadStop(TThread * const threadP ATTR_UNUSED) {
110     return TRUE;
111 }
112
113
114
115 abyss_bool
116 ThreadKill(TThread * const threadP ATTR_UNUSED) {
117
118     return (pthread_kill(threadP->thread, SIGTERM) == 0);
119 }
120
121
122
123 void
124 ThreadWaitAndRelease(TThread * const threadP) {
125
126     void * threadReturn;
127
128     pthread_join(threadP->thread, &threadReturn);
129
130     free(threadP);
131 }
132
133
134
135 void
136 ThreadExit(int const retValue) {
137
138     pthread_exit((void*)&retValue);
139
140     /* Note that the above runs our cleanup routine (which we registered
141        with pthread_cleanup_push() before exiting.
142     */
143 }
144
145
146
147 void
148 ThreadRelease(TThread * const threadP) {
149
150     pthread_detach(threadP->thread);
151
152     free(threadP);
153 }
154
155
156
157 abyss_bool
158 ThreadForks(void) {
159
160     return FALSE;
161 }
162
163
164
165 void
166 ThreadUpdateStatus(TThread * const threadP ATTR_UNUSED) {
167
168     /* Threads keep their own statuses up to date, so there's nothing
169        to do here.
170     */
171 }
172
173
174
175 void
176 ThreadHandleSigchld(pid_t const pid ATTR_UNUSED) {
177
178     /* Death of a child signals have nothing to do with pthreads */
179 }
180
181
182
183 /*********************************************************************
184 ** Mutex
185 *********************************************************************/
186
187
188
189 abyss_bool
190 MutexCreate(TMutex * const mutexP) {
191
192     return (pthread_mutex_init(mutexP, NULL) == 0);
193 }
194
195
196
197 abyss_bool
198 MutexLock(TMutex * const mutexP) {
199     return (pthread_mutex_lock(mutexP) == 0);
200 }
201
202
203
204 abyss_bool
205 MutexUnlock(TMutex * const mutexP) {
206     return (pthread_mutex_unlock(mutexP) == 0);
207 }
208
209
210
211 abyss_bool
212 MutexTryLock(TMutex * const mutexP) {
213     return (pthread_mutex_trylock(mutexP) == 0);
214 }
215
216
217
218 void
219 MutexFree(TMutex * const mutexP) {
220     pthread_mutex_destroy(mutexP);
221 }