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

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

#1 fix posix-thread scheduling mechanism on solaris

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