comparison Isolated/SimpleThreadPosix.c @ 38:71b465ff0622

Added support files.
author Eric Wing <ewing@anscamobile.com>
date Thu, 28 Apr 2011 16:22:30 -0700
parents
children
comparison
equal deleted inserted replaced
37:b346b6608eab 38:71b465ff0622
1 #include "SimpleThread.h"
2 #include <stddef.h>
3 #include <stdlib.h>
4 #include <pthread.h>
5 #include <signal.h>
6
7 #if defined(DEBUG)
8 #include <stdio.h>
9 #define THRDDBG(x) printf x
10 #else
11 #define THRDDBG(x)
12 #endif
13
14
15 struct SimpleThread
16 {
17 size_t threadID;
18 pthread_t nativeThread;
19 int threadStatus;
20 // void* userData;
21 };
22
23 typedef struct SimpleThreadArguments
24 {
25 int (*userFunction)(void*);
26 void* userData;
27 SimpleThread* simpleThread;
28 } SimpleThreadArguments;
29
30
31
32 static void* Internal_RunThread(void* user_data)
33 {
34 int (*user_function)(void*);
35 void* function_user_data;
36 int* status_val;
37
38 #if 0
39 /* disable signals */
40 sigset_t disable_set;
41
42 /*
43 in the main thread, set up the desired signal mask, common to most threads
44 any newly created threads will inherit this signal mask
45 */
46 sigemptyset(&disable_set);
47 sigaddset(&disable_set, SIGHUP);
48 sigaddset(&disable_set, SIGINT);
49 sigaddset(&disable_set, SIGUSR1);
50 sigaddset(&disable_set, SIGUSR2);
51 sigaddset(&disable_set, SIGALRM);
52 sigaddset(&disable_set, SIGQUIT);
53 sigaddset(&disable_set, SIGPIPE);
54 sigaddset(&disable_set, SIGTERM);
55 sigaddset(&disable_set, SIGCHLD);
56 sigaddset(&disable_set, SIGWINCH);
57 sigaddset(&disable_set, SIGVTALRM);
58 sigaddset(&disable_set, SIGPROF);
59
60
61 /* block out these signals */
62 sigprocmask(SIG_BLOCK, &disable_set, NULL);
63 #endif
64
65 SimpleThreadArguments* simple_thread_arguments = (SimpleThreadArguments*)user_data;
66 simple_thread_arguments->simpleThread->threadID = SimpleThread_GetCurrentThreadID();
67
68 user_function = simple_thread_arguments->userFunction;
69 function_user_data = simple_thread_arguments->userData;
70 status_val = &simple_thread_arguments->simpleThread->threadStatus;
71
72
73 /* I hope this is safe to delete on a different thread than it was created for. */
74 free(simple_thread_arguments);
75
76 *status_val = user_function(function_user_data);
77
78 pthread_exit(NULL);
79 return NULL;
80 }
81
82
83 SimpleThread* SimpleThread_CreateThread(int (*user_function)(void*), void* user_data)
84 {
85 pthread_attr_t thread_attributes;
86 int ret_val;
87 SimpleThread* new_thread;
88 SimpleThreadArguments* simple_thread_arguments;
89
90 new_thread = (SimpleThread*)malloc(sizeof(SimpleThread));
91 if(NULL == new_thread)
92 {
93 THRDDBG(("Out of memory.\n"));
94 return NULL;
95 }
96
97 ret_val = pthread_attr_init(&thread_attributes);
98 if(0 != ret_val)
99 {
100 /* failed */
101 THRDDBG(("pthread_attr_init failed with: %d\n", ret_val));
102 free(new_thread);
103 return 0;
104 }
105 ret_val = pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
106 if(0 != ret_val)
107 {
108 THRDDBG(("pthread_attr_setdetachstate failed with: %d\n", ret_val));
109 free(new_thread);
110 return NULL;
111 }
112
113 simple_thread_arguments = (SimpleThreadArguments*)malloc(sizeof(SimpleThreadArguments));
114 if(NULL == simple_thread_arguments)
115 {
116 THRDDBG(("Out of memory.\n"));
117 free(new_thread);
118 return NULL;
119 }
120 simple_thread_arguments->userFunction = user_function;
121 simple_thread_arguments->userData = user_data;
122 simple_thread_arguments->simpleThread = new_thread;
123
124 ret_val = pthread_create(&new_thread->nativeThread, &thread_attributes, Internal_RunThread, simple_thread_arguments);
125 if(0 != ret_val)
126 {
127 THRDDBG(("pthread_create failed with: %d\n", ret_val));
128 free(simple_thread_arguments);
129 free(new_thread);
130 return NULL;
131 }
132
133 return new_thread;
134 }
135
136
137
138 size_t SimpleThread_GetCurrentThreadID()
139 {
140 return (size_t)pthread_self();
141 }
142
143 void SimpleThread_WaitThread(SimpleThread* simple_thread, int* thread_status)
144 {
145 int ret_val;
146 if(NULL == simple_thread)
147 {
148 THRDDBG(("SimpleThread_WaitThread was passed NULL\n"));
149 return;
150 }
151
152
153 ret_val = pthread_join(simple_thread->nativeThread, 0);
154 if(0 != ret_val)
155 {
156 THRDDBG(("pthread_join failed with: %d\n", ret_val));
157 }
158 if(NULL != thread_status)
159 {
160 *thread_status = simple_thread->threadStatus;
161 }
162 free(simple_thread);
163 }
164
165 size_t SimpleThread_GetThreadID(SimpleThread* simple_thread)
166 {
167 if(NULL == simple_thread)
168 {
169 THRDDBG(("SimpleThread_GetThreadID was passed NULL\n"));
170 return 0;
171 }
172 return simple_thread->threadID;
173 }
174
175
176 int SimpleThread_GetThreadPriority(SimpleThread* simple_thread)
177 {
178 struct sched_param schedule_param;
179 int sched_policy;
180 int ret_val;
181
182 if(NULL == simple_thread)
183 {
184 THRDDBG(("SimpleThread_GetThreadPriority was passed NULL\n"));
185 return -1; /* Not sure what to return. Do other platforms use negative numbers? */
186 }
187 ret_val = pthread_getschedparam(simple_thread->nativeThread, &sched_policy, &schedule_param);
188 if(0 != ret_val)
189 {
190 THRDDBG(("SimpleThread_GetThreadPriority pthread_getschedparam failed with: %d\n", ret_val));
191 return -1;
192 }
193 return schedule_param.sched_priority;
194 }
195
196 void SimpleThread_SetThreadPriority(SimpleThread* simple_thread, int priority_level)
197 {
198 struct sched_param schedule_param;
199 int ret_val;
200
201 if(NULL == simple_thread)
202 {
203 THRDDBG(("SimpleThread_SetThreadPriority was passed NULL\n"));
204 return;
205 }
206 schedule_param.sched_priority = priority_level; /* PTHREAD_MIN_PRIORITY=0 to PTHREAD_MAX_PRIORITY=31 */
207 ret_val = pthread_setschedparam(simple_thread->nativeThread, SCHED_OTHER, &schedule_param);
208 if(0 != ret_val)
209 {
210 THRDDBG(("SimpleThread_SetThreadPriority pthread_setschedparam failed with: %d\n", ret_val));
211 return;
212 }
213 }
214