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
RevLine 
[4]1/**
[119]2 * \file cf_thread.c
3 * \author myusgun <myusgun@gmail.com>
[117]4 *
[119]5 * \brief 멀티 스레드 및 뮤텍스 구현
[4]6 */
7#include "cf_thread.h"
8#include "cf_local.h"
[40]9#include "cf_error.h"
[4]10
11#include <stdlib.h>
12
[50]13#if defined(_WIN32) || defined(_WIN64)
[4]14# include <windows.h>
15# include <process.h>
16# define THREAD_TYPE HANDLE
17# define MUTEX_TYPE HANDLE
[57]18# define THREAD_RETURN unsigned long /**< 스레드 워커 함수 반환 형 */
19# define THREAD_CALL __stdcall
[50]20#else // #if defined(_WIN32) || defined(_WIN64)
[4]21# include <pthread.h>
22# define THREAD_TYPE pthread_t
23# define MUTEX_TYPE pthread_mutex_t
[57]24# define THREAD_RETURN void * /**< 스레드 워커 함수 반환 형 */
25# define THREAD_CALL
[50]26#endif // #if defined(_WIN32) || defined(_WIN64)
[4]27
[122]28#define ASSERT_THREAD_CTX(__ctx) \
29 if (__ctx == NULL) \
30 return CF_ERROR_THREAD_INVALID_CTX
[4]31
[122]32#define ASSERT_MUTEX_CTX(__ctx) \
33 if (__ctx == NULL) \
34 return CF_ERROR_MUTEX_INVALID_CTX
[4]35
[65]36typedef THREAD_RETURN (THREAD_CALL * THREAD_WORKER) (void *);
[60]37
[122]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
[23]50static int
[122]51CF_Thread_Local_Close (THREAD_TYPE tid)
[4]52{
[50]53#if defined(_WIN32) || defined(_WIN64)
[123]54 if (tid == NULL)
55 return CF_ERROR_THREAD_INVALID_ARGS;
56
[122]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)
[123]67 if (mid == NULL)
68 return CF_ERROR_MUTEX_INVALID_ARGS;
69
[122]70 CloseHandle (mid);
[4]71#else
[122]72 pthread_mutex_destroy (&mid);
[4]73#endif
74
75 return CF_OK;
76}
77
[35]78/**
[122]79 * 스레드 컨텍스트를 생성
[35]80 *
[119]81 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]82 *
[122]83 * \param ctx 스레드 컨텍스트 주소
[119]84 * \param callback 스레드 워커 함수 이름
85 * \param arg 스레드 함수로 전달할 인자
[122]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 * 스레드를 실행
[80]108 *
[122]109 * \return 성공 시, CF_OK; 실패 시, 오류 코드
110 *
111 * \param ctx 스레드 컨텍스트
112 *
[119]113 * \remarks
[122]114 * pthread에서 지원되는 스케줄링 정책은 SCHED_OTHER, SCHED_FIFO, SCHED_RR 등이 존재 <br />
[80]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 />
[35]121 */
[4]122int
[122]123CF_Thread_Start (CF_Thread_Ctx ctx)
[4]124{
125 int result = 0;
126
[122]127 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
[57]128
[122]129 ASSERT_THREAD_CTX (ctx);
130
[50]131#if defined(_WIN32) || defined(_WIN64)
[122]132 context->tid = CreateThread (NULL, 0, context->callback, context->arg, 0, NULL);
133 if (context->tid == NULL)
134 return CF_ERROR_THREAD_START;
[81]135#else
[57]136
[81]137 pthread_attr_t * attr = NULL;
[80]138# if defined(_SOLARIS)
[81]139 pthread_attr_t solarisAttr;
140 struct sched_param sched;
[4]141
[81]142 attr = &solarisAttr;
[80]143
[81]144 result = pthread_attr_init (attr);
145 if (result)
146 return CF_ERROR_THREAD_INIT_ATTR;
[80]147
[81]148 result = pthread_attr_setinheritsched (attr, PTHREAD_EXPLICIT_SCHED);
149 if (result)
150 return CF_ERROR_THREAD_SET_INHERIT_SCHED;
[80]151
[81]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;
[80]160# endif // # if defined(_SOLARIS)
161
[122]162 result = pthread_create (&context->tid, attr, context->callback, context->arg);
[84]163 if (result)
[122]164 return CF_ERROR_THREAD_START;
[81]165#endif
[80]166 return result;
[4]167}
168
[35]169/**
[122]170 * 스레드 컨텍스트를 해제
[35]171 *
[119]172 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]173 *
[122]174 * \param ctx 스레드 컨텍스트
[35]175 *
[122]176 * \remarks 스레드 컨텍스트를 해제하는 것이며 워커 스레드가 종료되지 않음
[35]177 */
[4]178int
[122]179CF_Thread_DestroyCtx (CF_Thread_Ctx ctx)
[4]180{
[122]181 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
[4]182
[122]183 ASSERT_THREAD_CTX (ctx);
184
185 CF_Thread_Local_Close (context->tid);
186 free (context);
187
188 return CF_OK;
[4]189}
190
[35]191/**
192 * 스레드가 종료될 때 까지 대기
193 *
[119]194 * \return CF_OK 반환
[35]195 *
[122]196 * \param ctx 스레드 컨텍스트
[35]197 */
[4]198int
[122]199CF_Thread_Join (CF_Thread_Ctx ctx)
[4]200{
[122]201 CF_THREAD_CTX * context = (CF_THREAD_CTX *) ctx;
[4]202
[122]203 char status[16] = {0x00,};
204
205 ASSERT_THREAD_CTX (ctx);
206
[50]207#if defined(_WIN32) || defined(_WIN64)
[122]208 WaitForSingleObject (context->tid, INFINITE);
[4]209#else
[122]210 pthread_join (context->tid, (void **)status);
[4]211#endif
212
213 return CF_OK;
214}
215
[35]216/**
[122]217 * 뮤텍스 컨텍스트를 생성
[35]218 *
[119]219 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]220 *
[122]221 * \param ctx 뮤텍스 컨텍스트 주소
[35]222 */
[4]223int
[122]224CF_Mutex_CreateCtx (CF_Mutex_Ctx * ctx)
[4]225{
226 int result = 0;
227
[122]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 {
[50]236#if defined(_WIN32) || defined(_WIN64)
[122]237 context->mid = CreateMutexA (NULL, FALSE, NULL);
[123]238 if (context->mid == NULL)
[122]239 {
240 result = CF_ERROR_MUTEX_CREATE;
241 TRY_BREAK;
242 }
[4]243#else
[122]244 result = pthread_mutex_init (&context->mid, NULL);
245 if (result)
246 {
247 result = CF_ERROR_MUTEX_CREATE;
248 TRY_BREAK;
249 }
[4]250#endif
[123]251
252 *ctx = context;
[122]253 }
254 CATCH_IF (result < 0)
255 {
[123]256 CF_Mutex_DestoryCtx ((CF_Mutex_Ctx) context);
[122]257 }
[4]258
[123]259 return result;
[4]260}
261
[35]262/**
[122]263 * 뮤텍스 컨텍스트 해제
[35]264 *
[119]265 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]266 *
[122]267 * \param ctx 뮤텍스 컨텍스트
[35]268 */
[4]269int
[122]270CF_Mutex_DestoryCtx (CF_Mutex_Ctx ctx)
[4]271{
[122]272 CF_MUTEX_CTX * context = ctx;
[4]273
[122]274 ASSERT_MUTEX_CTX (ctx);
275
276 CF_Mutex_Local_Close (context->mid);
277 free (context);
278
279 return CF_OK;
[4]280}
281
[35]282/**
283 * 뮤텍스 잠금
284 *
[119]285 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]286 *
[122]287 * \param ctx 뮤텍스 컨텍스트
[35]288 */
[4]289int
[122]290CF_Mutex_Lock (CF_Mutex_Ctx ctx)
[4]291{
[122]292 CF_MUTEX_CTX * context = ctx;
[4]293
[122]294 ASSERT_MUTEX_CTX (ctx);
295
[50]296#if defined(_WIN32) || defined(_WIN64)
[122]297 WaitForSingleObject (context->mid, INFINITE);
[4]298#else
[122]299 pthread_mutex_lock (&context->mid);
[4]300#endif
301
302 return CF_OK;
303}
304
[35]305/**
306 * 뮤텍스 잠금 해제
307 *
[119]308 * \return 성공 시, CF_OK; 실패 시, 오류 코드
[35]309 *
[122]310 * \param ctx 뮤텍스 컨텍스트
[35]311 */
[4]312int
[122]313CF_Mutex_Unlock (CF_Mutex_Ctx ctx)
[4]314{
[122]315 CF_MUTEX_CTX * context = ctx;
[4]316
[122]317 ASSERT_MUTEX_CTX (ctx);
318
[50]319#if defined(_WIN32) || defined(_WIN64)
[122]320 ReleaseMutex (context->mid);
[4]321#else
[122]322 pthread_mutex_unlock (&context->mid);
[4]323#endif
324
325 return CF_OK;
326}
Note: See TracBrowser for help on using the repository browser.