OSDN Git Service

Import UnkoTim212
[timidity41/timidity41.git] / timidity / thread.c
1
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif /* HAVE_CONFIG_H */
6 #ifdef __POCC__
7 #include <sys/types.h>
8 #endif // for off_t
9 #include "interface.h"
10 #include <stdio.h>
11 #ifdef HAVE_STDLIB_H
12 #include <stdlib.h>
13 #endif /* HAVE_STDLIB_H */
14
15 #ifndef NO_STRING_H
16 #include <string.h>
17 #else
18 #include <strings.h>
19 #endif
20 #include <math.h>
21 #ifdef __W32__
22 #include <windows.h>
23 #endif /* __W32__ */
24 #ifdef HAVE_PTHREAD_H
25 #include <pthread.h>
26 #endif /* HAVE_PTHREAD_H */
27 #ifdef HAVE_PTHREADS_H
28 #include <pthreads.h>
29 #endif /* HAVE_PTHREADS_H */
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif /* HAVE_UNISTD_H */
33
34 #include "timidity.h"
35 #include "common.h"
36 #include "optcode.h"
37 #include "instrum.h"
38 #include "playmidi.h"
39 #include "controls.h"
40
41 #include "thread.h"
42 #ifdef __W32__
43 #include "w32g.h"
44 #endif /* __W32__ */
45
46
47
48 /*
49 win\88È\8aO\82Ìunix/linux/mac\93\99\82Å\82Íposix
50
51 Win\82Å\82Ì\83X\83\8c\83b\83h\8d\\91¢\83e\83X\83g
52 test1 \96\88\89ñbeginthread \94ñ\8fí\82É\92x\82¢
53 test2 \96\88\89ñResumeThread/SuspendThread \91½\83X\83\8c\83b\83h\82Å\92x\82¢ Sleep\83\8b\81[\83v\82É\82æ\82é\95s\97v\82È\8bó\89ñ\82è\82ª\82ÅCPU\95\89\89×\8d\82\82¢
54 test3 \82¸\82Á\82Æ\83X\83\8c\83b\83h\89ñ\82µ\82Á\82Ï\82È\82µ \82â\82â\92x\82¢ \93®\8dì\82ª\89ö\82µ\82¢ \83{\83c
55 test4 \8dÄ\90\92\86\82Ü\82í\82µ\82Á\82Ï\82È\82µ\88ê\92è\8e\9e\8aÔ\8cã\83X\83\8c\83b\83h\8fI\97¹ CPU\83X\83\8c\83b\83h\90\94\82Ì\82Æ\82«\92x\82­\82È\82é (\83R\83\93\83g\83\8d\81[\83\8b\97p\83X\83\8c\83b\83h\92Ç\89Á\82Ì\95ª CPU\83X\83\8c\83b\83h\90\94\82æ\82è\8eÀ\8ds\83X\83\8c\83b\83h\82ª\91½\82­\82È\82é
56 test5 Event\82Å\83X\83\8c\83b\83h\82ð\83R\83\93\83g\83\8d\81[\83\8b \91½\83X\83\8c\83b\83h\82Å\91¬\82¢ Sleep\83\8b\81[\83v\82É\82æ\82é\95s\97v\82È\8bó\89ñ\82è\82ª\82È\82¢\82Ì\82ÅCPU\95\89\89×\8f­\82È\82¢ \83X\83\8c\83b\83h\8fI\97¹\83C\83x\83\93\83g\91Ò\8b@\82ÌWaitForMulti\82ª\92x\82¢\82æ\82¤\82È\81E\81E\81H
57 test6 test5\82Ì\83X\83\8c\83b\83h\8fI\97¹\83C\83x\83\93\83g\91Ò\8b@\82ð_mm_pause()\83\8b\81[\83v\82É\82µ\82½\82à\82Ì test5\82æ\82è\91¬\82¢ \83\81\83C\83\93\83X\83\8c\83b\83h\82Ì\95\89\89×\82Í\91\9d\82¦\82é
58 test7 test6+load_balance \8d×\82©\82­\95ª\8a\84\82µ\82½job\82ð\8bó\82¢\82Ä\82é\83X\83\8c\83b\83h\82É\8a\84\82è\93\96\82Ä \83X\83\8c\83b\83h\8aÔ\82Ì\8f\88\97\9d\97Ê\82Ì\8d·\82ð\8c¸\82ç\82· mutex\8eg\97p test6\82æ\82è\91¬\82¢
59 test8 test7\82Ìmutex\82ðCRITICAL_SECTION\82É\95Ï\8dX  test7\82æ\82è\91¬\82¢
60 test9 test8+reload \88ê\93x\8eÀ\8ds\82µ\82½\83X\83\8c\83b\83h\8a\84\82è\93\96\82Ä\82ð\8bL\98^\82µ \88ê\92è\8e\9e\8aÔ\93¯\8aú\82È\82µ\82Å\8eÀ\8ds test7\82­\82ç\82¢\82É\92x\82­\82È\82Á\82½ \83{\83c
61 */
62
63
64 int compute_thread_num = 0;
65 int compute_thread_ready = 0;
66
67 void go_compute_thread(thread_func_t fnc, int num);
68 void terminate_compute_thread(void);
69 void begin_compute_thread(void);
70 void reset_compute_thread(void);
71 static void do_compute_null(int thread_num){}
72 static thread_func_t do_compute_func = do_compute_null;
73 static int compute_thread_job = 0, compute_thread_job_cnt = 0;
74
75
76 #if defined(MULTI_THREAD_COMPUTE) && defined(__W32__)
77
78 static int thread_exit = 0;
79 static HANDLE hComputeThread[MAX_THREADS - 1];
80 VOLATILE DWORD ComputeThreadID[MAX_THREADS - 1];
81 static DWORD ComputeThreadPriority = THREAD_PRIORITY_NORMAL;
82 static HANDLE hEventTcv[MAX_THREADS - 1];
83 static ALIGN uint8 thread_finish_all[MAX_THREADS]; // byte*16=64bit*2=128bit
84 static ALIGN uint8 thread_finish[MAX_THREADS]; // byte*16=64bit*2=128bit
85 CRITICAL_SECTION critThread;
86
87 void set_compute_thread_priority(DWORD var)
88 {
89         ComputeThreadPriority = var;
90 }
91
92 #if (USE_X86_EXT_INTRIN >= 3)
93 #define THREAD_WAIT_MAIN _mm_pause(); // SSE2
94 #define THREAD_WAIT_SUB Sleep(0);
95 #else
96 #define THREAD_WAIT_MAIN Sleep(0);
97 #define THREAD_WAIT_SUB Sleep(0);
98 // \91¼\82Ì\83X\83\8c\83b\83h\82É\8f\88\97\9d\82ð\93n\82·(\8dÅ\8f¬\8e\9e\8aÔ) \82±\82ê\82ª\82È\82¢\82Æ\95\89\89×\91\9d\89Á
99 // OS\83f\83t\83H\83\8b\83g\82Å\82Í1~15\82Ì\8ew\92è\8e\9e 15.6ms 
100 #endif
101
102 static void compute_thread_core(int thread_num)
103 {               
104         if(compute_thread_job <= compute_thread_ready){
105                 if(thread_num < compute_thread_job)
106                         do_compute_func(thread_num);
107         }else{
108 #if 1 // load_balance // \8bó\82¢\82Ä\82é\83X\83\8c\83b\83h\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
109                 for(;;){
110                         int job_num;
111                         EnterCriticalSection(&critThread); // single thread ~
112                         job_num = (compute_thread_job_cnt++);
113                         LeaveCriticalSection(&critThread); // ~ single thread
114                         if(job_num >= compute_thread_job) break;
115                         do_compute_func(job_num);
116                 }
117 #else // normal // \83X\83\8c\83b\83h\82É\8bÏ\93\99\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
118                 int i;
119                 for (i = thread_num; i < compute_thread_job; i += compute_thread_ready)
120                         do_compute_func(i);
121 #endif
122         }
123 }
124
125 static void WINAPI ComputeThread(void *arglist)
126 {
127         const int thread_num = (int)arglist;
128         
129         for(;;){                
130                 WaitForSingleObject(hEventTcv[thread_num], INFINITE); // \83X\83\8c\83b\83h\8aJ\8en\83C\83x\83\93\83g\91Ò\8b@
131                 if(thread_exit) break;          
132                 compute_thread_core(thread_num + 1); // 1~15
133                 ResetEvent(hEventTcv[thread_num]); // \83X\83\8c\83b\83h\8aJ\8en\83C\83x\83\93\83g\83\8a\83Z\83b\83g
134                 thread_finish[thread_num] = 1; // \83X\83\8c\83b\83h\8fI\97¹\83t\83\89\83O\83Z\83b\83g
135         }
136         crt_endthread();
137 }
138
139 static inline void compute_thread_wait(void)
140 {       
141 // (MAX_THREADS == 16)
142 #if (USE_X86_EXT_INTRIN >= 6)
143         // byte*8\82ð128bit\92P\88Ê\82Å\94ä\8ar
144         __m128i vec = _mm_load_si128((__m128i *)thread_finish_all);
145         while(!_mm_testc_si128(_mm_load_si128((__m128i *)thread_finish), vec)) // SSE4.1 !(finish == finish_all)
146                 THREAD_WAIT_MAIN
147 #else
148         // byte*8\82ð64bit\92P\88Ê\82Å\94ä\8a
149         uint64 *ptr1 = (uint64 *)&thread_finish, *ptr2 = (uint64 *)&thread_finish_all;
150         while(ptr1[0] != ptr2[0] || ptr1[1] != ptr2[1])
151                 THREAD_WAIT_MAIN
152 #endif
153 }
154
155 void go_compute_thread(thread_func_t fnc, int num)
156 {
157         const int thread = compute_thread_ready - 1;
158         int i;
159
160         do_compute_func = fnc;
161         compute_thread_job = num;
162         compute_thread_job_cnt = 0;
163 #if (USE_X86_EXT_INTRIN >= 3) && (MAX_THREADS == 16)
164         _mm_store_si128((__m128i *)thread_finish, _mm_setzero_si128());  // \83X\83\8c\83b\83h\8fI\97¹\83t\83\89\83O\83\8a\83Z\83b\83g
165         for(i = 0; i < thread; i++)
166                 SetEvent(hEventTcv[i]); // \83X\83\8c\83b\83h\8aJ\8en\83C\83x\83\93\83g\83Z\83b\83g (\8dÄ\8aJ)
167 #else
168         for(i = 0; i < thread; i++){
169                 thread_finish[i] = 0;  // \83X\83\8c\83b\83h\8fI\97¹\83t\83\89\83O\83\8a\83Z\83b\83g
170                 SetEvent(hEventTcv[i]); // \83X\83\8c\83b\83h\8aJ\8en\83C\83x\83\93\83g\83Z\83b\83g (\8dÄ\8aJ)
171         }
172 #endif
173         compute_thread_core(0);
174         compute_thread_wait(); // \91S\83X\83\8c\83b\83h\8fI\97¹\91Ò\8b@
175 }
176
177 static void init_compute_thread_param(void)
178 {
179         static int thread_init = 0;
180         int i;
181
182         if(thread_init)
183                 return;
184         for(i = 0; i < (MAX_THREADS - 1); i++){
185                 hComputeThread[i] = NULL;
186         }       
187         memset(thread_finish, 0, MAX_THREADS);
188         memset(thread_finish_all, 0, MAX_THREADS);      
189         InitializeCriticalSection(&critThread); 
190         compute_thread_ready = 0;
191         thread_init = 1; // set init flag
192 }
193
194 static int check_compute_thread(void)
195 {       
196         int i, flg = 0;
197
198         for(i = 0; i < (MAX_THREADS - 1); i++){
199                 if(hComputeThread[i] != NULL)
200                         flg++;
201         }
202         if(flg){
203                 terminate_compute_thread();
204                 compute_thread_ready = 0;
205                 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : already thread exsist.");
206                 return 1;       
207         }
208         return 0;       
209 }
210
211 void terminate_compute_thread(void)
212 {
213         int i;
214         DWORD status;
215         
216         thread_exit = 1;
217         compute_thread_job = 0; // \83f\83b\83h\83\8d\83b\83N\91Î\8dô
218         for(i = 0; i < (MAX_THREADS - 1); i++){
219                 if(hComputeThread[i] == NULL)
220                         continue;               
221                 SetEvent(hEventTcv[i]);
222                 switch(WaitForSingleObject(hComputeThread[i], 10)) {
223                 case WAIT_OBJECT_0:
224                         break;
225                 case WAIT_TIMEOUT:
226                         status = WaitForSingleObject(hComputeThread[i], 1000);
227                         if(status == WAIT_TIMEOUT)
228                                 TerminateThread(hComputeThread[i], 0);
229                         break;
230                 default:
231                         TerminateThread(hComputeThread[i], 0);
232                         break;
233                 }
234                 CloseHandle(hComputeThread[i]);
235                 hComputeThread[i] = NULL;
236         }       
237         for(i = 0; i < (MAX_THREADS - 1); i++){
238                 if(hEventTcv[i] != NULL){
239                         CloseHandle(hEventTcv[i]);
240                         hEventTcv[i] = NULL;
241                 }
242         }
243         memset(thread_finish, 0, MAX_THREADS);
244         memset(thread_finish_all, 0, MAX_THREADS);      
245         DeleteCriticalSection(&critThread);     
246         compute_thread_ready = 0;
247         thread_exit = 0;
248         uninit_compute_data_midi_thread();
249 }
250
251 // load ini, load config , init_playmidi()... \82Ì\8cã\82É\82·\82é
252 void begin_compute_thread(void)
253 {
254         int i, pnum, error = 0;                 
255         SYSTEM_INFO sys_info;
256
257         GetSystemInfo(&sys_info);
258         pnum = sys_info.dwNumberOfProcessors;
259         ctl->cmsg(CMSG_INFO, VERB_NORMAL, "NumberOfProcessors : %d", pnum);
260
261         init_compute_thread_param(); // init thread param       
262         if(check_compute_thread()) // check thread exist
263                 return; 
264         if(compute_thread_num < 2){ // check thread num
265                 compute_thread_num = 0;
266                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "SetComputeThread : OFF");
267         }else{
268                 if(compute_thread_num > MAX_THREADS){ // check thread num
269                         compute_thread_num = MAX_THREADS;
270                         ctl->cmsg(CMSG_INFO, VERB_NORMAL, "ERROR ComputeThread : Limit MAX_THREADS:%d", MAX_THREADS);
271                 }
272                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "SetComputeThread : %d", compute_thread_num);
273         }
274         if(compute_thread_num == 0) // check multi thread
275                 return;         
276         // beginthread after CreateEvent
277         InitializeCriticalSection(&critThread); 
278         for(i = 0; i < (compute_thread_num - 1); i++){  
279                 hEventTcv[i] = CreateEvent(NULL,FALSE,FALSE,NULL); // reset manual
280                 thread_finish_all[i] = 1; // 1byte full bit
281                 if(hEventTcv[i] == NULL){
282                         ++error;
283                         ctl->cmsg(CMSG_INFO, VERB_NORMAL, "ERROR ComputeThread: CreateEvent(%d) error.", i);
284                         break;
285                 }
286                 hComputeThread[i] = crt_beginthreadex(
287                                 NULL, 
288                                 0,
289                                 (LPTHREAD_START_ROUTINE)ComputeThread, 
290                                 (LPVOID)i, /* void *arglist = thread_num */
291                                 0, /* initflag = NULL or CREATE_SUSPENDED */
292                                 &(ComputeThreadID[i])
293                                 );
294                 if(hComputeThread[i] == NULL){
295                         ++error;
296                         ctl->cmsg(CMSG_INFO, VERB_NORMAL, "ERROR ComputeThread : beginthread(%d) error.", i);
297                         break;
298                 }
299         }       
300         if(error){
301                 terminate_compute_thread();
302                 compute_thread_ready = 0;
303                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "SetComputeThread : OFF");
304                 return;
305         }
306         compute_thread_ready = compute_thread_num;
307         switch(ComputeThreadPriority){
308         case THREAD_PRIORITY_LOWEST:
309         case THREAD_PRIORITY_BELOW_NORMAL:
310         case THREAD_PRIORITY_NORMAL:
311         case THREAD_PRIORITY_ABOVE_NORMAL:
312         case THREAD_PRIORITY_HIGHEST:
313         case THREAD_PRIORITY_TIME_CRITICAL:
314                 for(i = 0; i < (compute_thread_ready - 1); i++)
315                         if(!SetThreadPriority(hComputeThread[i], ComputeThreadPriority)){
316                                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "ERROR ComputeThread : Invalid priority");
317                         }
318                 break;
319         default:
320                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "ERROR ComputeThread : Invalid priority");
321                 break;
322         }       
323         init_compute_data_midi_thread();
324     return;
325 }
326
327 void reset_compute_thread(void)
328 {
329         if(compute_thread_num == compute_thread_ready)
330                 return;
331         terminate_compute_thread();
332         begin_compute_thread();
333 }
334
335
336 #elif 0 // defined(MULTI_THREAD_COMPUTE) && (defined(HAVE_PTHREAD_H) || defined(HAVE_PTHREADS_H)) && defined(HAVE_PTHREAD_CREATE)
337 /*
338 \88ê\89\9e\93®\82¢\82Ä\82Í\82¢\82é\82ª\94ñ\8fí\82É\92x\82¢\81E\81ECPU\8eg\97p\97¦\82ª\91S\91R\8fã\82ª\82ç\82È\82¢\81E\81E
339 cond_wait/cond_signal\82ª\92x\82¢\82Ì\82Å\82Í\81E\81E\81H
340 Linux\82Å\82Í\8d\82\91¬\82È\83X\83\8c\83b\83h\8b@\94\\82Í\82È\82¢\82Ì\82©\81\91¼\82É\89½\82©\82 \82é\82Ì\82©\81H
341
342 \8eg\97p\82·\82é\8fê\8d\87\82Í\8ae\83t\83@\83\93\83N\83V\83\87\83\93\82Ì\8ed\97l\82ð\8am\94F\82µ\82½\8fã\82Å\93®\8dì\83e\83X\83g\82·\82é
343 \8eQ\8dl\82É\82µ\82½\82Ì\82Í PTHREADS-WIN32 RELEASE 2.8.0 (2006-12-22) \82Å POSIX\82»\82Ì\82à\82Ì\82Å\82Í\82È\82¢\82Ì\82Å\81E\81E
344 Win\90ê\97p\95\94\95ª\82ðPTHREAD\83t\83@\83\93\83N\83V\83\87\83\93\82É\92u\82«\8a·\82¦\82½\82à\82Ì
345
346 CRITICAL_SECTION\82Ípthread_mutex_ , EVENT\82Ípthread_cond_\93\99\82Å\91ã\91Ö
347
348 pthread_create()                \88È\91O\82©\82ç\8eg\97p\82µ\82Ä\82é\82Ì\82Å\82½\82Ô\82ñOK
349 pthread_join()                  \88È\91O\82©\82ç\8eg\97p\82µ\82Ä\82é\82Ì\82Å\82½\82Ô\82ñOK
350 pthread_????                    \83X\83\8c\83b\83h\82ª\82 \82é/\82È\82µ\82Ì\8fó\91Ô\8eæ\93¾ \95s\96¾ (\82È\82­\82Ä\82à\93®\82­
351 pthread_mutex_init()    \88ø\90\94\82ª\82 \82â\82µ\82¢ \8b¤\97L\83t\83\89\83O\81H\81H
352 pthread_mutex_destroy() CloseHandle()\82Æ\93¯\82¶ 
353 pthread_mutex_lock()    WaitForSingleObject()\82Æ\93¯\82
354 pthread_mutex_unlock()  ReleaseMutex()\82Æ\93¯\82
355 pthread_cond_init()             \88ø\90\94\82ª\82 \82â\82µ\82¢ \8b¤\97L\83t\83\89\83O\81H\81H
356 pthread_cond_destroy()  CloseHandle()\82Æ\93¯\82¶ 
357 pthread_cond_wait()             WaitForSingleObject()\82Æ\93¯\82\81H\81H CPU\8e\9e\8aÔ\8fÁ\94ï\82·\82é\82Ì\82©\82Ç\82¤\82©\81H mutex_lock\82ª\95K\97v\82ç\82µ\82¢
358 pthread_cond_signal()   SetEvent()\82Æ\93¯\82\81H\81H
359 pthread_????                    ResetEvent()\91\8a\93\96\82Ì\82à\82Ì\96³\82¢\81\83V\83O\83i\83\8b\82Í\8e©\93®\83\8a\83Z\83b\83g\81
360 */
361
362 static int thread_exit = 0;
363 static pthread_t handle_thread[MAX_THREADS - 1];
364 pthread_cond_t cond_thread[MAX_THREADS - 1];
365 static ALIGN int8 thread_finish_all[MAX_THREADS]; // byte*16=64bit*2=128bit
366 static ALIGN int8 thread_finish[MAX_THREADS]; // byte*16=64bit*2=128bit
367 pthread_mutex_t mutex_job;
368 pthread_mutex_t mutex_thread[MAX_THREADS];
369
370 #if (USE_X86_EXT_INTRIN >= 3)
371 #define THREAD_WAIT_MAIN _mm_pause(); // SSE2
372 #else
373 #define THREAD_WAIT_MAIN usleep(0);
374 #endif
375
376 static void compute_thread_core(int thread_num)
377 {
378         if(compute_thread_job <= compute_thread_ready){
379                 if(thread_num < compute_thread_job)
380                         do_compute_func(thread_num);
381         }else{  
382 #if 1 // load_balancer  // \8bó\82¢\82Ä\82é\83X\83\8c\83b\83h\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
383                 for(;;){
384                         int job_num;
385                         pthread_mutex_lock(&mutex_job); // \83~\83\85\81[\83e\83b\83N\83X\8eæ\93¾
386                         job_num = (compute_thread_job_cnt++);
387                         pthread_mutex_unlock(&mutex_job); // \83~\83\85\81[\83e\83b\83N\83X\89ð\95ú                 
388                         if(job_num >= compute_thread_job) break;
389                         do_compute_func(job_num);
390                 }
391 #else // normal // \83X\83\8c\83b\83h\82É\8bÏ\93\99\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
392                 int i;
393                 for (i = thread_num; i < compute_thread_job; i += compute_thread_ready)
394                         do_compute_func(i);
395 #endif
396         }
397 }
398
399 static void *ComputeThread(void *arglist)
400 {
401         const int thread_num = (int)arglist;
402         
403         for(;;){
404         //      pthread_mutex_lock(&mutex_thread[thread_num]); // \83~\83\85\81[\83e\83b\83N\83X\8eæ\93¾
405                 pthread_cond_wait(&cond_thread[thread_num], &mutex_thread[thread_num]); // \83X\83\8c\83b\83h\8aJ\8en\83V\83O\83i\83\8b\91Ò\8b@ . \83V\83O\83i\83\8b\8cã\91Ò\8b@\8fó\91Ô\82É\96ß\82é\81H
406         //      pthread_mutex_unlock(&mutex_thread[thread_num]);
407                 if(thread_exit) break;          
408                 compute_thread_core(thread_num + 1); // 1~15
409                 // \83\8d\83b\83N\97p\82Ì\83V\83O\83i\83\8b\82È\82¢\81H cond_wait\82Í\8e©\93®\83\8a\83Z\83b\83g\81H
410                 thread_finish[thread_num] = 1;
411         }
412         return 0;
413 }
414
415 static inline void compute_thread_wait(void)
416 {       
417 // (MAX_THREADS == 16)
418 #if (USE_X86_EXT_INTRIN >= 6)
419          // byte*8\82ð128bit\92P\88Ê\82Å\94ä\8ar
420         __m128i vec = _mm_load_si128((__m128i *)thread_finish_all);
421         while(!_mm_testc_si128(_mm_load_si128((__m128i *)thread_finish), vec)) // SSE4.1 !(finish == finish_all)
422                 THREAD_WAIT_MAIN
423 #else // byte*8\82ð64bit\92P\88Ê\82Å\94ä\8ar
424         uint64 *ptr1 = (uint64 *)&thread_finish, *ptr2 = (uint64 *)&thread_finish_all;
425         while(ptr1[0] != ptr2[0] || ptr1[1] != ptr2[1])
426                 THREAD_WAIT_MAIN
427 #endif
428 }
429
430 void go_compute_thread(thread_func_t fnc, int num)
431 {
432         const int thread = compute_thread_ready - 1;
433         int i;
434                 
435         do_compute_func = fnc;
436         compute_thread_job = num;
437         compute_thread_job_cnt = 0;
438 #if (USE_X86_EXT_INTRIN >= 3) && (MAX_THREADS == 16)
439         _mm_store_si128((__m128i *)thread_finish, _mm_setzero_si128());  // \83X\83\8c\83b\83h\8fI\97¹\83t\83\89\83O\83\8a\83Z\83b\83g
440         for(i = 0; i < thread; i++){            
441                 pthread_mutex_lock(&mutex_thread[i]); // \83~\83\85\81[\83e\83b\83N\83X\8eæ\93¾
442                 pthread_cond_signal(&cond_thread[i]); // \83X\83\8c\83b\83h\8aJ\8en\83V\83O\83i\83\8b\83Z\83b\83g (\8dÄ\8aJ)
443                 pthread_mutex_unlock(&mutex_thread[i]); // \83~\83\85\81[\83e\83b\83N\83X\89ð\95ú
444         }
445 #else
446         for (i = 0; i < thread; i++) {
447                 thread_finish[i] = 0;  // \83X\83\8c\83b\83h\8fI\97¹\83t\83\89\83O\83\8a\83Z\83b\83g            
448                 pthread_mutex_lock(&mutex_thread[i]); // \83~\83\85\81[\83e\83b\83N\83X\8eæ\93¾
449                 pthread_cond_signal(&cond_thread[i]); // \83X\83\8c\83b\83h\8aJ\8en\83V\83O\83i\83\8b\83Z\83b\83g (\8dÄ\8aJ)
450                 pthread_mutex_unlock(&mutex_thread[i]); // \83~\83\85\81[\83e\83b\83N\83X\89ð\95ú
451         }
452 #endif
453         compute_thread_core(0); // thread 0
454         compute_thread_wait(); // \91S\83X\83\8c\83b\83h\8fI\97¹\91Ò\8b@
455 }
456
457 static void init_compute_thread_param(void)
458 {
459         static int thread_init = 0;
460         int i;
461
462         if (thread_init)
463                 return;
464         //for (i = 0; i < (MAX_THREADS - 1); i++){
465         //      // \83n\83\93\83h\83\8b\82©\82È\82É\82©\82Ì\8f\89\8aú\89»
466         //}
467         memset(thread_finish, 0, MAX_THREADS);
468         memset(thread_finish_all, 0, MAX_THREADS);      
469         compute_thread_ready = 0;
470         thread_init = 1; // set init flag
471 }
472
473 static int check_compute_thread(void)
474 {
475         int i, flg = 0;
476         
477         // \82±\82±\82Å\83X\83\8c\83b\83h\82ª\8ec\82Á\82Ä\82é\82±\82Æ\82Í\82È\82¢\82Í\82¸
478         //for (i = 0; i < (MAX_THREADS - 1); i++) {
479         //      if () // \83X\83\8c\83b\83h\82ª\82 \82é\82Ì\8fð\8c\8f \83n\83\93\83h\83\8b\82©\82È\82É\82©\82Ì\83`\83F\83b\83N\81H
480         //              flg++;
481         //}
482         //if(flg){
483         //      terminate_compute_thread();
484         //      compute_thread_ready = 0;
485         //      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : already thread exist.");
486         //      return 1;       
487         //}
488         return 0;
489 }
490
491 void terminate_compute_thread(void)
492 {
493         int i;
494                 
495         thread_exit = 1;
496         compute_thread_job = 0; // \83f\83b\83h\83\8d\83b\83N\91Î\8dô
497         for(i = 0; i < (MAX_THREADS - 1); i++){
498                 //if() // \83X\83\8c\83b\83h\82ª\82È\82¢\82Ì\8fð\8c\8f
499                 //      continue;       
500                 pthread_mutex_lock(&mutex_thread[i]);
501                 pthread_cond_signal(&cond_thread[i]); // \83X\83\8c\83b\83h\8aJ\8en\83V\83O\83i\83\8b\83Z\83b\83g (\8dÄ\8aJ)
502                 pthread_mutex_unlock(&mutex_thread[i]);
503                 pthread_join(handle_thread[i], NULL);
504                 handle_thread[i] = NULL;
505         }       
506         for(i = 0; i < (MAX_THREADS - 1); i++){
507                 pthread_mutex_destroy(&mutex_thread[i]);
508                 pthread_cond_destroy(&cond_thread[i]);
509         }       
510         pthread_mutex_destroy(&mutex_job);
511         memset(thread_finish, 0, MAX_THREADS);
512         memset(thread_finish_all, 0, MAX_THREADS);      
513         compute_thread_ready = 0;
514         thread_exit = 0;
515         uninit_compute_data_midi_thread();
516 }
517
518 // load ini, load config , init_playmidi()... \82Ì\8cã\82É\82·\82é
519 void begin_compute_thread(void)
520 {
521         int i, error = 0;
522
523         init_compute_thread_param(); // init thread param
524         if (check_compute_thread()) // check thread exist
525                 return;
526         if (compute_thread_num > MAX_THREADS) // check thread num
527                 compute_thread_num = MAX_THREADS;
528         else if (compute_thread_num < 2) // check thread num
529                 compute_thread_num = 0;
530         if (compute_thread_num == 0) // check multi thread
531                 return;
532         if(pthread_mutex_init(&mutex_job, NULL)){
533                 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : pthread_mutex_init mutex_job error.");
534                 error++;
535         }else for(i = 0; i < (compute_thread_num - 1); i++){    
536                 if(pthread_mutex_init(&mutex_thread[i], NULL)){
537                         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : pthread_mutex_init %d error.", i);
538                         error++;
539                         break;
540                 }
541                 if(pthread_cond_init(&cond_thread[i], NULL)){ // attr\82Í\8b¤\97L\90Ý\92è\81
542                         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : pthread_cond_init %d error.", i);
543                         error++;
544                         break;
545                 }
546                 thread_finish_all[i] = 1;
547                 if(pthread_create(&handle_thread[i], NULL, (void*)ComputeThread, (void*)i)){
548                         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : pthread_create %d error.", i);
549                         error++;
550                         break;
551                 }
552         }               
553         if(error){
554                 terminate_compute_thread();
555                 compute_thread_ready = 0;
556                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "SetComputeThread : OFF");
557                 return;
558         }
559         compute_thread_ready = compute_thread_num;
560         init_compute_data_midi_thread();
561     return;
562 }
563
564 void reset_compute_thread(void)
565 {
566         if (compute_thread_num == compute_thread_ready)
567                 return;
568         terminate_compute_thread();
569         begin_compute_thread();
570 }
571
572 #elif defined(MULTI_THREAD_COMPUTE) && (defined(HAVE_PTHREAD_H) || defined(HAVE_PTHREADS_H)) && defined(HAVE_PTHREAD_CREATE)
573 /*
574 \88ê\89\9e\93®\82¢\82Ä\82Í\82¢\82é\82ª\81E\81E\92x\82¢\82æ\82¤\82È\81E\81E\81H
575
576 \96\88\89ñpthread_create/pthread_join
577 load_balancer (mutex)  // CRITICAL_SECTION\82ª\82È\82¢\81H\82Ì\82Åmutex\8eg\97p
578 */
579
580 static pthread_t handle_thread[MAX_THREADS - 1];
581 pthread_mutex_t mutex_job;
582
583 static void compute_thread_core(int thread_num)
584 {       
585         if(compute_thread_job <= compute_thread_ready){
586                 if(thread_num < compute_thread_job)
587                         do_compute_func(thread_num);
588         }else{  
589 #if 1 // load_balancer  // \8bó\82¢\82Ä\82é\83X\83\8c\83b\83h\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
590                 for(;;){
591                         int job_num;
592                         pthread_mutex_lock(&mutex_job); // \83~\83\85\81[\83e\83b\83N\83X\8eæ\93¾
593                         job_num = (compute_thread_job_cnt++);
594                         pthread_mutex_unlock(&mutex_job); // \83~\83\85\81[\83e\83b\83N\83X\89ð\95ú                 
595                         if(job_num >= compute_thread_job) break;
596                         do_compute_func(job_num);
597                 }
598 #else // normal // \83X\83\8c\83b\83h\82É\8bÏ\93\99\82É\83W\83\87\83u\8a\84\82è\93\96\82Ä
599                 int i;
600                 for (i = thread_num; i < compute_thread_job; i += compute_thread_ready)
601                         do_compute_func(i);
602 #endif
603         }
604 }
605
606 static void *ComputeThread(void *arglist)
607 {
608         compute_thread_core((int)arglist + 1); // 1~15
609         return 0;
610 }
611
612 void go_compute_thread(thread_func_t fnc, int num)
613 {
614         int i;
615                 
616         do_compute_func = fnc;
617         compute_thread_job = num;
618         compute_thread_job_cnt = 0;
619         for (i = 0; i < (compute_thread_ready - 1); i++)
620                 pthread_create(&handle_thread[i], NULL, (void*)ComputeThread, (void*)i);
621         compute_thread_core(0);
622         for (i = 0; i < (compute_thread_ready - 1); i++)
623                 pthread_join(handle_thread[i], NULL);
624 }
625
626 static void init_compute_thread_param(void)
627 {
628         static int thread_init = 0;
629         int i;
630
631         if (thread_init)
632                 return;
633         compute_thread_ready = 0;
634         thread_init = 1; // set init flag
635 }
636
637 void terminate_compute_thread(void)
638 {
639         pthread_mutex_destroy(&mutex_job);
640         compute_thread_ready = 0;
641         uninit_compute_data_midi_thread();
642 }
643
644 // load ini, load config , init_playmidi()... \82Ì\8cã\82É\82·\82é
645 void begin_compute_thread(void)
646 {
647         int i, error = 0;
648
649         init_compute_thread_param(); // init thread param
650         if (compute_thread_num > MAX_THREADS) // check thread num
651                 compute_thread_num = MAX_THREADS;
652         else if (compute_thread_num < 2) // check thread num
653                 compute_thread_num = 0;
654         if (compute_thread_num == 0) // check multi thread
655                 return; 
656         if(pthread_mutex_init(&mutex_job, NULL)){
657                 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "ERROR ComputeThread : pthread_mutex_init thread_core error.");
658                 error++;
659         }               
660         if(error){
661                 terminate_compute_thread();
662                 compute_thread_ready = 0;
663                 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "SetComputeThread : OFF");
664                 return;
665         }
666         compute_thread_ready = compute_thread_num;
667         init_compute_data_midi_thread();
668     return;
669 }
670
671 void reset_compute_thread(void)
672 {
673         if (compute_thread_num == compute_thread_ready)
674                 return;
675         terminate_compute_thread();
676         begin_compute_thread();
677 }
678 #endif /* MULTI_THREAD_COMPUTE */