source: libcf/trunk/src/cf_thread.c@ 123

Last change on this file since 123 was 123, checked in by cheese, 11 years ago

#1 fix windows bug for r122

File size: 6.8 KB
Line 
1/**
2 * \file cf_thread.c
3 * \author myusgun <myusgun@gmail.com>
4 *
5 * \brief 멀티 스레드 및 뮤텍스 구현
6 */
7#include "cf_thread.h"
8#include "cf_local.h"
9#include "cf_error.h"
10
11#include <stdlib.h>
12
13#if defined(_WIN32) || defined(_WIN64)
14# include <windows.h>
15# include <process.h>
16# define THREAD_TYPE HANDLE
17# define MUTEX_TYPE HANDLE
18# define THREAD_RETURN unsigned long /**< 스레드 워커 함수 반환 형 */
19# define THREAD_CALL __stdcall
20#else // #if defined(_WIN32) || defined(_WIN64)
21# include <pthread.h>
22# define THREAD_TYPE pthread_t
23# define MUTEX_TYPE pthread_mutex_t
24# define THREAD_RETURN void * /**< 스레드 워커 함수 반환 형 */
25# define THREAD_CALL
26#endif // #if defined(_WIN32) || defined(_WIN64)
27
28#define ASSERT_THREAD_CTX(__ctx) \
29 if (__ctx == NULL) \
30 return CF_ERROR_THREAD_INVALID_CTX
31
32#define ASSERT_MUTEX_CTX(__ctx) \
33 if (__ctx == NULL) \
34 return CF_ERROR_MUTEX_INVALID_CTX
35
36typedef THREAD_RETURN (THREAD_CALL * THREAD_WORKER) (void *);
37
38typedef struct __cf_thread_ctx__
39{
40 THREAD_TYPE tid;
41 THREAD_WORKER callback;
42 void * arg;
43} CF_THREAD_CTX;
44
45typedef struct __cf_ctx_ctx__
46{
47 MUTEX_TYPE mid;
48} CF_MUTEX_CTX;
49
50static int
51CF_Thread_Local_Close (THREAD_TYPE tid)
52{
53#if defined(_WIN32) || defined(_WIN64)
54 if (tid == NULL)
55 return CF_ERROR_THREAD_INVALID_ARGS;
56
57 CloseHandle (tid);
58#endif
59
60 return CF_OK;
61}
62
63static int
64CF_Mutex_Local_Close (MUTEX_TYPE mid)
65{
66#if defined(_WIN32) || defined(_WIN64)
67 if (mid == NULL)
68 return CF_ERROR_MUTEX_INVALID_ARGS;
69
70 CloseHandle (mid);
71#else
72 pthread_mutex_destroy (&mid);
73#endif
74
75 return CF_OK;
76}
77
78/**
79 * 스레드 컨텍스트를 생성
80 *
81 * \return 성공 시, CF_OK; 실패 시, 오류 코드
82 *
83 * \param ctx 스레드 컨텍스트 주소
84 * \param callback 스레드 워커 함수 이름
85 * \param arg 스레드 함수로 전달할 인자
86 */
87int
88CF_Thread_CreateCtx (CF_Thread_Ctx * ctx,
89 CF_Thread_Function callback,
90 void * arg)
91{
92 CF_THREAD_CTX * context = NULL;
93
94 context = (CF_THREAD_CTX *) calloc (sizeof (CF_THREAD_CTX), 1);
95 if (context == NULL)
96 return CF_ERROR_THREAD_CREATE_CTX;
97
98 context->callback = (THREAD_WORKER) callback;
99 context->arg = arg;
100
101 *ctx = (CF_Thread_Ctx) context;
102
103 return CF_OK;
104}
105
106/**
107 * 스레드를 실행
108 *
109 * \return 성공 시, CF_OK; 실패 시, 오류 코드
110 *
111 * \param ctx 스레드 컨텍스트
112 *
113 * \remarks
114 * pthread에서 지원되는 스케줄링 정책은 SCHED_OTHER, SCHED_FIFO, SCHED_RR 등이 존재 <br />
115 * 일반적으로 설정되는 스케줄링 정책의 기본값은 SCHED_OTHER이며, 솔라리스 환경에서 SCHED_OTHER는 TS(timesharing) 방식으로 명시되어 있음 <br />
116 * 그러나 개발 단계에서 테스트된 동작은 SCHED_FIFO와 동일하였으며, 때문에 솔라리스 환경에서는 스케줄링 정책을 SCHED_RR로 명시하도록 함 <br />
117 * <br />
118 * 참고 url <br />
119 * - http://kldp.org/node/18841 , "SCHED_OTHER, SCHED_FIFO, SCHED_RR에 대해..." <br />
120 * - http://blog.naver.com/popjunior/80021646476 , "AIX, CPU 모니터링과 튜닝" <br />
121 */
122int
123CF_Thread_Start (CF_Thread_Ctx ctx)
124{
125 int result = 0;
126
127 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
128
129 ASSERT_THREAD_CTX (ctx);
130
131#if defined(_WIN32) || defined(_WIN64)
132 context->tid = CreateThread (NULL, 0, context->callback, context->arg, 0, NULL);
133 if (context->tid == NULL)
134 return CF_ERROR_THREAD_START;
135#else
136
137 pthread_attr_t * attr = NULL;
138# if defined(_SOLARIS)
139 pthread_attr_t solarisAttr;
140 struct sched_param sched;
141
142 attr = &solarisAttr;
143
144 result = pthread_attr_init (attr);
145 if (result)
146 return CF_ERROR_THREAD_INIT_ATTR;
147
148 result = pthread_attr_setinheritsched (attr, PTHREAD_EXPLICIT_SCHED);
149 if (result)
150 return CF_ERROR_THREAD_SET_INHERIT_SCHED;
151
152 result = pthread_attr_setschedpolicy (attr, SCHED_RR);
153 if (result)
154 return CF_ERROR_THREAD_SET_SCHED_POLICY;
155
156 sched.sched_priority = 1;
157 result = pthread_attr_setschedparam (attr, &sched);
158 if (result)
159 return CF_ERROR_THREAD_SET_SCHED_PARAM;
160# endif // # if defined(_SOLARIS)
161
162 result = pthread_create (&context->tid, attr, context->callback, context->arg);
163 if (result)
164 return CF_ERROR_THREAD_START;
165#endif
166 return result;
167}
168
169/**
170 * 스레드 컨텍스트를 해제
171 *
172 * \return 성공 시, CF_OK; 실패 시, 오류 코드
173 *
174 * \param ctx 스레드 컨텍스트
175 *
176 * \remarks 스레드 컨텍스트를 해제하는 것이며 워커 스레드가 종료되지 않음
177 */
178int
179CF_Thread_DestroyCtx (CF_Thread_Ctx ctx)
180{
181 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
182
183 ASSERT_THREAD_CTX (ctx);
184
185 CF_Thread_Local_Close (context->tid);
186 free (context);
187
188 return CF_OK;
189}
190
191/**
192 * 스레드가 종료될 때 까지 대기
193 *
194 * \return CF_OK 반환
195 *
196 * \param ctx 스레드 컨텍스트
197 */
198int
199CF_Thread_Join (CF_Thread_Ctx ctx)
200{
201 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
202
203 char status[16] = {0x00,};
204
205 ASSERT_THREAD_CTX (ctx);
206
207#if defined(_WIN32) || defined(_WIN64)
208 WaitForSingleObject (context->tid, INFINITE);
209#else
210 pthread_join (context->tid, (void **)status);
211#endif
212
213 return CF_OK;
214}
215
216/**
217 * 뮤텍스 컨텍스트를 생성
218 *
219 * \return 성공 시, CF_OK; 실패 시, 오류 코드
220 *
221 * \param ctx 뮤텍스 컨텍스트 주소
222 */
223int
224CF_Mutex_CreateCtx (CF_Mutex_Ctx * ctx)
225{
226 int result = 0;
227
228 CF_MUTEX_CTX * context = NULL;
229
230 context = (CF_MUTEX_CTX *) calloc (sizeof (CF_MUTEX_CTX), 1);
231 if (context == NULL)
232 return CF_ERROR_MUTEX_CREATE_CTX;
233
234 TRY
235 {
236#if defined(_WIN32) || defined(_WIN64)
237 context->mid = CreateMutexA (NULL, FALSE, NULL);
238 if (context->mid == NULL)
239 {
240 result = CF_ERROR_MUTEX_CREATE;
241 TRY_BREAK;
242 }
243#else
244 result = pthread_mutex_init (&context->mid, NULL);
245 if (result)
246 {
247 result = CF_ERROR_MUTEX_CREATE;
248 TRY_BREAK;
249 }
250#endif
251
252 *ctx = context;
253 }
254 CATCH_IF (result < 0)
255 {
256 CF_Mutex_DestoryCtx ((CF_Mutex_Ctx) context);
257 }
258
259 return result;
260}
261
262/**
263 * 뮤텍스 컨텍스트 해제
264 *
265 * \return 성공 시, CF_OK; 실패 시, 오류 코드
266 *
267 * \param ctx 뮤텍스 컨텍스트
268 */
269int
270CF_Mutex_DestoryCtx (CF_Mutex_Ctx ctx)
271{
272 CF_MUTEX_CTX * context = ctx;
273
274 ASSERT_MUTEX_CTX (ctx);
275
276 CF_Mutex_Local_Close (context->mid);
277 free (context);
278
279 return CF_OK;
280}
281
282/**
283 * 뮤텍스 잠금
284 *
285 * \return 성공 시, CF_OK; 실패 시, 오류 코드
286 *
287 * \param ctx 뮤텍스 컨텍스트
288 */
289int
290CF_Mutex_Lock (CF_Mutex_Ctx ctx)
291{
292 CF_MUTEX_CTX * context = ctx;
293
294 ASSERT_MUTEX_CTX (ctx);
295
296#if defined(_WIN32) || defined(_WIN64)
297 WaitForSingleObject (context->mid, INFINITE);
298#else
299 pthread_mutex_lock (&context->mid);
300#endif
301
302 return CF_OK;
303}
304
305/**
306 * 뮤텍스 잠금 해제
307 *
308 * \return 성공 시, CF_OK; 실패 시, 오류 코드
309 *
310 * \param ctx 뮤텍스 컨텍스트
311 */
312int
313CF_Mutex_Unlock (CF_Mutex_Ctx ctx)
314{
315 CF_MUTEX_CTX * context = ctx;
316
317 ASSERT_MUTEX_CTX (ctx);
318
319#if defined(_WIN32) || defined(_WIN64)
320 ReleaseMutex (context->mid);
321#else
322 pthread_mutex_unlock (&context->mid);
323#endif
324
325 return CF_OK;
326}
Note: See TracBrowser for help on using the repository browser.