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

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

#1 more fix and arrange doxygen comments

File size: 5.7 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(__h) \
29 if (__h == NULL) \
30 return CF_ERROR_THREAD_INVALID_ARGS
31
32#define ASSERT_MUTEX(__h) \
33 if (__h == NULL) \
34 return CF_ERROR_MUTEX_INVALID_ARGS
35
36typedef THREAD_RETURN (THREAD_CALL * THREAD_WORKER) (void *);
37
38static int
39CF_Thread_Local_Close (void * ctx)
40{
41#if defined(_WIN32) || defined(_WIN64)
42 CloseHandle (ctx);
43#else
44 free (ctx);
45#endif
46
47 return CF_OK;
48}
49
50/**
51 * 스레드를 생성
52 *
53 * @return 성공 시, CF_OK; 실패 시, 오류 코드
54 *
55 * @param threadID 스레드 아이디 주소
56 * @param callback 스레드 워커 함수 이름
57 * @param arg 스레드 함수로 전달할 인자
58 *
59 * @remarks
60 * pthread(POSIX Thread)에서 지원되는 스케줄링 정책은 SCHED_OTHER, SCHED_FIFO, SCHED_RR 등이 존재 <br />
61 * 일반적으로 설정되는 스케줄링 정책의 기본값은 SCHED_OTHER이며, 솔라리스 환경에서 SCHED_OTHER는 TS(timesharing) 방식으로 명시되어 있음 <br />
62 * 그러나 개발 단계에서 테스트된 동작은 SCHED_FIFO와 동일하였으며, 때문에 솔라리스 환경에서는 스케줄링 정책을 SCHED_RR로 명시하도록 함 <br />
63 * <br />
64 * 참고 url <br />
65 * - http://kldp.org/node/18841 , "SCHED_OTHER, SCHED_FIFO, SCHED_RR에 대해..." <br />
66 * - http://blog.naver.com/popjunior/80021646476 , "AIX, CPU 모니터링과 튜닝" <br />
67 */
68int
69CF_Thread_CreateCtx (CF_Thread_Ctx * threadID,
70 CF_Thread_Function callback,
71 void * arg)
72{
73 int result = 0;
74
75 THREAD_WORKER f = (THREAD_WORKER) callback;
76
77#if defined(_WIN32) || defined(_WIN64)
78 *threadID = (THREAD_TYPE) CreateThread (NULL, 0, f, arg, 0, NULL);
79 if (*threadID == NULL)
80 return CF_ERROR_THREAD_CREATE;
81#else
82
83 pthread_attr_t * attr = NULL;
84# if defined(_SOLARIS)
85 pthread_attr_t solarisAttr;
86 struct sched_param sched;
87
88 attr = &solarisAttr;
89
90 result = pthread_attr_init (attr);
91 if (result)
92 return CF_ERROR_THREAD_INIT_ATTR;
93
94 result = pthread_attr_setinheritsched (attr, PTHREAD_EXPLICIT_SCHED);
95 if (result)
96 return CF_ERROR_THREAD_SET_INHERIT_SCHED;
97
98 result = pthread_attr_setschedpolicy (attr, SCHED_RR);
99 if (result)
100 return CF_ERROR_THREAD_SET_SCHED_POLICY;
101
102 sched.sched_priority = 1;
103 result = pthread_attr_setschedparam (attr, &sched);
104 if (result)
105 return CF_ERROR_THREAD_SET_SCHED_PARAM;
106# endif // # if defined(_SOLARIS)
107
108 *threadID = (THREAD_TYPE *) calloc (sizeof (THREAD_TYPE), 1);
109 if (*threadID == NULL)
110 return CF_ERROR_THREAD_CREATE_CTX;
111
112 result = pthread_create ((THREAD_TYPE *) *threadID, attr, f, arg);
113 if (result)
114 {
115 CF_Thread_DestroyCtx (threadID);
116 return CF_ERROR_THREAD_CREATE;
117 }
118
119#endif
120 return result;
121}
122
123/**
124 * 스레드 아이디를 해제
125 *
126 * @return 성공 시, CF_OK; 실패 시, 오류 코드
127 *
128 * @param threadID 스레드 아이디 주소
129 *
130 * @remarks 스레드 아이디를 해제하는 것이며 워커 스레드가 종료되지 않음
131 */
132int
133CF_Thread_DestroyCtx (CF_Thread_Ctx * threadID)
134{
135 ASSERT_THREAD (*threadID);
136
137 return CF_Thread_Local_Close (*threadID);
138}
139
140/**
141 * 스레드가 종료될 때 까지 대기
142 *
143 * @return CF_OK 반환
144 *
145 * @param threadID 스레드 아이디 주소
146 */
147int
148CF_Thread_Join (CF_Thread_Ctx * threadID)
149{
150 ASSERT_THREAD (*threadID);
151
152#if defined(_WIN32) || defined(_WIN64)
153 WaitForSingleObject ((THREAD_TYPE) *threadID, INFINITE);
154#else
155 char status[16] = {0x00,};
156 pthread_join (*((THREAD_TYPE *) *threadID), (void **)status);
157#endif
158
159 return CF_OK;
160}
161
162/**
163 * 뮤텍스 생성
164 *
165 * @return 성공 시, CF_OK; 실패 시, 오류 코드
166 *
167 * @param mutex 뮤텍스 아이디 주소
168 *
169 * @see CF_Thread_Create
170 */
171int
172CF_Mutex_CreateCtx (CF_Mutex_Ctx * mutex)
173{
174 int result = 0;
175
176#if defined(_WIN32) || defined(_WIN64)
177 *mutex = (MUTEX_TYPE) CreateMutexA (NULL, FALSE, NULL);
178 if (*mutex == NULL)
179 return CF_ERROR_MUTEX_CREATE;
180#else
181 *mutex = (MUTEX_TYPE *) calloc (sizeof (MUTEX_TYPE), 1);
182 if (*mutex == NULL)
183 return CF_ERROR_MUTEX_CREATE;
184
185 result = pthread_mutex_init (*mutex, NULL);
186 if (result)
187 return CF_ERROR_MUTEX_CREATE;
188#endif
189
190 return CF_OK;
191}
192
193/**
194 * 뮤텍스 해제
195 *
196 * @return 성공 시, CF_OK; 실패 시, 오류 코드
197 *
198 * @param mutex 뮤텍스 아이디 주소
199 */
200int
201CF_Mutex_DestoryCtx (CF_Mutex_Ctx * mutex)
202{
203 ASSERT_MUTEX (*mutex);
204
205#if defined(_WIN32) || defined(_WIN64)
206#else
207 pthread_mutex_destroy (*mutex);
208#endif
209 return CF_Thread_Local_Close (*mutex);
210}
211
212/**
213 * 뮤텍스 잠금
214 *
215 * @return 성공 시, CF_OK; 실패 시, 오류 코드
216 *
217 * @param mutex 뮤텍스 아이디 주소
218 */
219int
220CF_Mutex_Lock (CF_Mutex_Ctx * mutex)
221{
222 ASSERT_MUTEX (*mutex);
223
224#if defined(_WIN32) || defined(_WIN64)
225 WaitForSingleObject ((MUTEX_TYPE) *mutex, INFINITE);
226#else
227 pthread_mutex_lock ((MUTEX_TYPE *) *mutex);
228#endif
229
230 return CF_OK;
231}
232
233/**
234 * 뮤텍스 잠금 해제
235 *
236 * @return 성공 시, CF_OK; 실패 시, 오류 코드
237 *
238 * @param mutex 뮤텍스 아이디 주소
239 */
240int
241CF_Mutex_Unlock (CF_Mutex_Ctx * mutex)
242{
243 ASSERT_MUTEX (*mutex);
244
245#if defined(_WIN32) || defined(_WIN64)
246 ReleaseMutex (*mutex);
247#else
248 pthread_mutex_unlock ((MUTEX_TYPE *) *mutex);
249#endif
250
251 return CF_OK;
252}
Note: See TracBrowser for help on using the repository browser.