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

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

#1 modify id to context in thread

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