Haiku supporting patches
[platform/upstream/openblas.git] / driver / others / blas_server.c
1 /*****************************************************************************
2 Copyright (c) 2011-2014, The OpenBLAS Project
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9    1. Redistributions of source code must retain the above copyright
10       notice, this list of conditions and the following disclaimer.
11
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in
14       the documentation and/or other materials provided with the
15       distribution.
16    3. Neither the name of the OpenBLAS project nor the names of 
17       its contributors may be used to endorse or promote products 
18       derived from this software without specific prior written 
19       permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
30 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 **********************************************************************************/
33
34 /*********************************************************************/
35 /* Copyright 2009, 2010 The University of Texas at Austin.           */
36 /* All rights reserved.                                              */
37 /*                                                                   */
38 /* Redistribution and use in source and binary forms, with or        */
39 /* without modification, are permitted provided that the following   */
40 /* conditions are met:                                               */
41 /*                                                                   */
42 /*   1. Redistributions of source code must retain the above         */
43 /*      copyright notice, this list of conditions and the following  */
44 /*      disclaimer.                                                  */
45 /*                                                                   */
46 /*   2. Redistributions in binary form must reproduce the above      */
47 /*      copyright notice, this list of conditions and the following  */
48 /*      disclaimer in the documentation and/or other materials       */
49 /*      provided with the distribution.                              */
50 /*                                                                   */
51 /*    THIS  SOFTWARE IS PROVIDED  BY THE  UNIVERSITY OF  TEXAS AT    */
52 /*    AUSTIN  ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,    */
53 /*    INCLUDING, BUT  NOT LIMITED  TO, THE IMPLIED  WARRANTIES OF    */
54 /*    MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR  PURPOSE ARE    */
55 /*    DISCLAIMED.  IN  NO EVENT SHALL THE UNIVERSITY  OF TEXAS AT    */
56 /*    AUSTIN OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,    */
57 /*    INCIDENTAL,  SPECIAL, EXEMPLARY,  OR  CONSEQUENTIAL DAMAGES    */
58 /*    (INCLUDING, BUT  NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE    */
59 /*    GOODS  OR  SERVICES; LOSS  OF  USE,  DATA,  OR PROFITS;  OR    */
60 /*    BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON ANY THEORY OF    */
61 /*    LIABILITY, WHETHER  IN CONTRACT, STRICT  LIABILITY, OR TORT    */
62 /*    (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT    */
63 /*    OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE    */
64 /*    POSSIBILITY OF SUCH DAMAGE.                                    */
65 /*                                                                   */
66 /* The views and conclusions contained in the software and           */
67 /* documentation are those of the authors and should not be          */
68 /* interpreted as representing official policies, either expressed   */
69 /* or implied, of The University of Texas at Austin.                 */
70 /*********************************************************************/
71
72 #include "common.h"
73 #if defined(OS_LINUX) || defined(OS_NETBSD) || defined(OS_DARWIN) || defined(OS_ANDROID) || defined(OS_SUNOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLY) || defined(OS_HAIKU)
74 #include <dlfcn.h>
75 #include <signal.h>
76 #include <sys/resource.h>
77 #include <sys/time.h>
78 #endif
79
80 #ifndef likely
81 #ifdef __GNUC__
82 #define likely(x) __builtin_expect(!!(x), 1)
83 #else
84 #define likely(x) (x)
85 #endif
86 #endif
87 #ifndef unlikely
88 #ifdef __GNUC__
89 #define unlikely(x) __builtin_expect(!!(x), 0)
90 #else
91 #define unlikely(x) (x)
92 #endif
93 #endif
94
95 extern unsigned int openblas_thread_timeout();
96
97 #ifdef SMP_SERVER
98
99 #undef MONITOR
100 #undef TIMING
101 #undef TIMING_DEBUG
102 #undef NEED_STACKATTR
103
104 #define ATTRIBUTE_SIZE 128
105
106 /* This is a thread server model implementation.  The threads are   */
107 /* spawned at first access to blas library, and still remains until */
108 /* destruction routine is called.  The number of threads are        */
109 /* equal to "OMP_NUM_THREADS - 1" and thread only wakes up when     */
110 /* jobs is queued.                                                  */
111
112 /* We need this grobal for cheking if initialization is finished.   */
113 int blas_server_avail   __attribute__((aligned(ATTRIBUTE_SIZE))) = 0;
114
115 /* Local Variables */
116 #if   defined(USE_PTHREAD_LOCK)
117 static pthread_mutex_t  server_lock    = PTHREAD_MUTEX_INITIALIZER;
118 #elif defined(USE_PTHREAD_SPINLOCK)
119 static pthread_spinlock_t  server_lock = 0;
120 #else
121 static unsigned long server_lock       = 0;
122 #endif
123
124 #define THREAD_STATUS_SLEEP             2
125 #define THREAD_STATUS_WAKEUP            4
126
127 static pthread_t       blas_threads [MAX_CPU_NUMBER];
128
129 typedef struct {
130   blas_queue_t * volatile queue   __attribute__((aligned(ATTRIBUTE_SIZE)));
131
132 #if defined(OS_LINUX) && !defined(NO_AFFINITY)
133   int   node;
134 #endif
135
136   volatile long          status;
137
138   pthread_mutex_t        lock;
139   pthread_cond_t         wakeup;
140
141 } thread_status_t;
142
143 static thread_status_t thread_status[MAX_CPU_NUMBER] __attribute__((aligned(ATTRIBUTE_SIZE)));
144
145 #ifndef THREAD_TIMEOUT
146 #define THREAD_TIMEOUT  28
147 #endif
148
149 static unsigned int thread_timeout = (1U << (THREAD_TIMEOUT));
150
151 #ifdef MONITOR
152
153 /* Monitor is a function to see thread's status for every seconds. */
154 /* Usually it turns off and it's for debugging.                    */
155
156 static pthread_t      monitor_thread;
157 static int main_status[MAX_CPU_NUMBER];
158 #define MAIN_ENTER       0x01
159 #define MAIN_EXIT        0x02
160 #define MAIN_TRYLOCK     0x03
161 #define MAIN_LOCKSUCCESS 0x04
162 #define MAIN_QUEUING     0x05
163 #define MAIN_RECEIVING   0x06
164 #define MAIN_RUNNING1    0x07
165 #define MAIN_RUNNING2    0x08
166 #define MAIN_RUNNING3    0x09
167 #define MAIN_WAITING     0x0a
168 #define MAIN_SLEEPING    0x0b
169 #define MAIN_FINISH      0x0c
170 #define MAIN_DONE        0x0d
171 #endif
172
173 #define BLAS_QUEUE_FINISHED     3
174 #define BLAS_QUEUE_RUNNING      4
175
176 #ifdef TIMING
177 BLASLONG        exit_time[MAX_CPU_NUMBER];
178 #endif
179
180 static void legacy_exec(void *func, int mode, blas_arg_t *args, void *sb){
181
182       if (!(mode & BLAS_COMPLEX)){
183 #ifdef EXPRECISION
184         if (mode & BLAS_XDOUBLE){
185           /* REAL / Extended Double */
186           void (*afunc)(BLASLONG, BLASLONG, BLASLONG, xdouble,
187                         xdouble *, BLASLONG, xdouble *, BLASLONG,
188                         xdouble *, BLASLONG, void *) = func;
189
190           afunc(args -> m, args -> n, args -> k,
191                 ((xdouble *)args -> alpha)[0],
192                 args -> a, args -> lda,
193                 args -> b, args -> ldb,
194                 args -> c, args -> ldc, sb);
195         } else
196 #endif
197           if (mode & BLAS_DOUBLE){
198             /* REAL / Double */
199             void (*afunc)(BLASLONG, BLASLONG, BLASLONG, double,
200                           double *, BLASLONG, double *, BLASLONG,
201                           double *, BLASLONG, void *) = func;
202
203             afunc(args -> m, args -> n, args -> k,
204                   ((double *)args -> alpha)[0],
205                   args -> a, args -> lda,
206                   args -> b, args -> ldb,
207                   args -> c, args -> ldc, sb);
208           } else {
209             /* REAL / Single */
210             void (*afunc)(BLASLONG, BLASLONG, BLASLONG, float,
211                           float *, BLASLONG, float *, BLASLONG,
212                           float *, BLASLONG, void *) = func;
213
214             afunc(args -> m, args -> n, args -> k,
215                   ((float *)args -> alpha)[0],
216                   args -> a, args -> lda,
217                   args -> b, args -> ldb,
218                   args -> c, args -> ldc, sb);
219           }
220       } else {
221 #ifdef EXPRECISION
222         if (mode & BLAS_XDOUBLE){
223           /* COMPLEX / Extended Double */
224           void (*afunc)(BLASLONG, BLASLONG, BLASLONG, xdouble, xdouble,
225                         xdouble *, BLASLONG, xdouble *, BLASLONG,
226                         xdouble *, BLASLONG, void *) = func;
227
228           afunc(args -> m, args -> n, args -> k,
229                 ((xdouble *)args -> alpha)[0],
230                 ((xdouble *)args -> alpha)[1],
231                 args -> a, args -> lda,
232                 args -> b, args -> ldb,
233                 args -> c, args -> ldc, sb);
234         } else
235 #endif
236           if (mode & BLAS_DOUBLE){
237             /* COMPLEX / Double */
238           void (*afunc)(BLASLONG, BLASLONG, BLASLONG, double, double,
239                         double *, BLASLONG, double *, BLASLONG,
240                         double *, BLASLONG, void *) = func;
241
242           afunc(args -> m, args -> n, args -> k,
243                 ((double *)args -> alpha)[0],
244                 ((double *)args -> alpha)[1],
245                 args -> a, args -> lda,
246                 args -> b, args -> ldb,
247                 args -> c, args -> ldc, sb);
248           } else {
249             /* COMPLEX / Single */
250           void (*afunc)(BLASLONG, BLASLONG, BLASLONG, float, float,
251                         float *, BLASLONG, float *, BLASLONG,
252                         float *, BLASLONG, void *) = func;
253
254           afunc(args -> m, args -> n, args -> k,
255                 ((float *)args -> alpha)[0],
256                 ((float *)args -> alpha)[1],
257                 args -> a, args -> lda,
258                 args -> b, args -> ldb,
259                 args -> c, args -> ldc, sb);
260           }
261       }
262 }
263
264 #if defined(OS_LINUX) && !defined(NO_AFFINITY)
265 int gotoblas_set_affinity(int);
266 int gotoblas_set_affinity2(int);
267 int get_node(void);
268 #endif
269
270 static int increased_threads = 0;
271
272 static void* blas_thread_server(void *arg){
273
274   /* Thread identifier */
275   BLASLONG  cpu = (BLASLONG)arg;
276   unsigned int last_tick;
277   void *buffer, *sa, *sb;
278   blas_queue_t  *queue;
279
280 blas_queue_t *tscq;
281
282 #ifdef TIMING_DEBUG
283   unsigned long start, stop;
284 #endif
285
286 #if defined(OS_LINUX) && !defined(NO_AFFINITY)
287   if (!increased_threads)
288     thread_status[cpu].node = gotoblas_set_affinity(cpu + 1);
289   else
290     thread_status[cpu].node = gotoblas_set_affinity(-1);
291 #endif
292
293 #ifdef MONITOR
294   main_status[cpu] = MAIN_ENTER;
295 #endif
296
297   buffer = blas_memory_alloc(2);
298
299 #ifdef SMP_DEBUG
300   fprintf(STDERR, "Server[%2ld] Thread has just been spawned!\n", cpu);
301 #endif
302
303   while (1){
304
305 #ifdef MONITOR
306     main_status[cpu] = MAIN_QUEUING;
307 #endif
308
309 #ifdef TIMING
310     exit_time[cpu] = rpcc();
311 #endif
312
313       last_tick = (unsigned int)rpcc();
314
315         pthread_mutex_lock  (&thread_status[cpu].lock);
316         tscq=thread_status[cpu].queue;
317         pthread_mutex_unlock  (&thread_status[cpu].lock);
318
319         while(!tscq) {
320         YIELDING;
321
322         if ((unsigned int)rpcc() - last_tick > thread_timeout) {
323
324           pthread_mutex_lock  (&thread_status[cpu].lock);
325
326           if (!thread_status[cpu].queue) {
327             thread_status[cpu].status = THREAD_STATUS_SLEEP;
328             while (thread_status[cpu].status == THREAD_STATUS_SLEEP) {
329
330 #ifdef MONITOR
331               main_status[cpu] = MAIN_SLEEPING;
332 #endif
333
334               pthread_cond_wait(&thread_status[cpu].wakeup, &thread_status[cpu].lock);
335             }
336           }
337
338           pthread_mutex_unlock(&thread_status[cpu].lock);
339
340           last_tick = (unsigned int)rpcc();
341         }
342         pthread_mutex_lock  (&thread_status[cpu].lock);
343         tscq=thread_status[cpu].queue;
344         pthread_mutex_unlock  (&thread_status[cpu].lock);
345
346       }
347
348     queue = thread_status[cpu].queue;
349
350     if ((long)queue == -1) break;
351
352 #ifdef MONITOR
353     main_status[cpu] = MAIN_RECEIVING;
354 #endif
355
356 #ifdef TIMING_DEBUG
357     start = rpcc();
358 #endif
359
360     if (queue) {
361       int (*routine)(blas_arg_t *, void *, void *, void *, void *, BLASLONG) = queue -> routine;
362
363       pthread_mutex_lock  (&thread_status[cpu].lock);
364       thread_status[cpu].queue = (blas_queue_t *)1;
365       pthread_mutex_unlock  (&thread_status[cpu].lock);
366
367       sa = queue -> sa;
368       sb = queue -> sb;
369
370 #ifdef SMP_DEBUG
371       if (queue -> args) {
372         fprintf(STDERR, "Server[%2ld] Calculation started.  Mode = 0x%03x M = %3ld N=%3ld K=%3ld\n",
373                 cpu, queue->mode, queue-> args ->m, queue->args->n, queue->args->k);
374       }
375 #endif
376
377 #ifdef CONSISTENT_FPCSR
378       __asm__ __volatile__ ("ldmxcsr %0" : : "m" (queue -> sse_mode));
379       __asm__ __volatile__ ("fldcw %0"   : : "m" (queue -> x87_mode));
380 #endif
381
382 #ifdef MONITOR
383       main_status[cpu] = MAIN_RUNNING1;
384 #endif
385
386       if (sa == NULL) sa = (void *)((BLASLONG)buffer + GEMM_OFFSET_A);
387
388       if (sb == NULL) {
389         if (!(queue -> mode & BLAS_COMPLEX)){
390 #ifdef EXPRECISION
391           if (queue -> mode & BLAS_XDOUBLE){
392             sb = (void *)(((BLASLONG)sa + ((QGEMM_P * QGEMM_Q * sizeof(xdouble)
393                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
394           } else
395 #endif
396           if (queue -> mode & BLAS_DOUBLE){
397             sb = (void *)(((BLASLONG)sa + ((DGEMM_P * DGEMM_Q * sizeof(double)
398                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
399
400           } else {
401             sb = (void *)(((BLASLONG)sa + ((SGEMM_P * SGEMM_Q * sizeof(float)
402                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
403           }
404         } else {
405 #ifdef EXPRECISION
406           if (queue -> mode & BLAS_XDOUBLE){
407             sb = (void *)(((BLASLONG)sa + ((XGEMM_P * XGEMM_Q * 2 * sizeof(xdouble)
408                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
409           } else
410 #endif
411           if (queue -> mode & BLAS_DOUBLE){
412             sb = (void *)(((BLASLONG)sa + ((ZGEMM_P * ZGEMM_Q * 2 * sizeof(double)
413                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
414           } else {
415             sb = (void *)(((BLASLONG)sa + ((CGEMM_P * CGEMM_Q * 2 * sizeof(float)
416                                         + GEMM_ALIGN) & ~GEMM_ALIGN)) + GEMM_OFFSET_B);
417           }
418         }
419         queue->sb=sb;
420       }
421
422 #ifdef MONITOR
423         main_status[cpu] = MAIN_RUNNING2;
424 #endif
425
426       if (queue -> mode & BLAS_LEGACY) {
427         legacy_exec(routine, queue -> mode, queue -> args, sb);
428       } else
429         if (queue -> mode & BLAS_PTHREAD) {
430           void (*pthreadcompat)(void *) = queue -> routine;
431           (pthreadcompat)(queue -> args);
432         } else
433           (routine)(queue -> args, queue -> range_m, queue -> range_n, sa, sb, queue -> position);
434
435 #ifdef SMP_DEBUG
436       fprintf(STDERR, "Server[%2ld] Calculation finished!\n", cpu);
437 #endif
438
439 #ifdef MONITOR
440       main_status[cpu] = MAIN_FINISH;
441 #endif
442
443       // arm: make sure all results are written out _before_
444       // thread is marked as done and other threads use them
445       WMB;
446
447       pthread_mutex_lock  (&thread_status[cpu].lock);
448       thread_status[cpu].queue = (blas_queue_t * volatile) ((long)thread_status[cpu].queue & 0);  /* Need a trick */
449       pthread_mutex_unlock  (&thread_status[cpu].lock);
450       
451       WMB;
452
453     }
454
455 #ifdef MONITOR
456       main_status[cpu] = MAIN_DONE;
457 #endif
458
459 #ifdef TIMING_DEBUG
460     stop = rpcc();
461
462     fprintf(STDERR, "Thread[%ld] : %16lu %16lu (%8lu cycles)\n", cpu + 1,
463             start, stop,
464             stop - start);
465 #endif
466
467   }
468
469   /* Shutdown procedure */
470
471 #ifdef SMP_DEBUG
472       fprintf(STDERR, "Server[%2ld] Shutdown!\n",  cpu);
473 #endif
474
475   blas_memory_free(buffer);
476
477   //pthread_exit(NULL);
478
479   return NULL;
480 }
481
482 #ifdef MONITOR
483
484 static BLASLONG num_suspend = 0;
485
486 static int blas_monitor(void *arg){
487   int i;
488
489   while(1){
490     for (i = 0; i < blas_num_threads - 1; i++){
491       switch (main_status[i]) {
492       case MAIN_ENTER :
493         fprintf(STDERR, "THREAD[%2d] : Entering.\n", i);
494         break;
495       case MAIN_EXIT :
496         fprintf(STDERR, "THREAD[%2d] : Exiting.\n", i);
497         break;
498       case MAIN_TRYLOCK :
499         fprintf(STDERR, "THREAD[%2d] : Trying lock operation.\n", i);
500         break;
501       case MAIN_QUEUING :
502         fprintf(STDERR, "THREAD[%2d] : Queuing.\n", i);
503         break;
504       case MAIN_RECEIVING :
505         fprintf(STDERR, "THREAD[%2d] : Receiving.\n", i);
506         break;
507       case MAIN_RUNNING1 :
508         fprintf(STDERR, "THREAD[%2d] : Running1.\n", i);
509         break;
510       case MAIN_RUNNING2 :
511         fprintf(STDERR, "THREAD[%2d] : Running2.\n", i);
512         break;
513       case MAIN_RUNNING3 :
514         fprintf(STDERR, "THREAD[%2d] : Running3.\n", i);
515         break;
516       case MAIN_WAITING :
517         fprintf(STDERR, "THREAD[%2d] : Waiting.\n", i);
518         break;
519       case MAIN_SLEEPING :
520         fprintf(STDERR, "THREAD[%2d] : Sleeping.\n", i);
521         break;
522       case MAIN_FINISH :
523         fprintf(STDERR, "THREAD[%2d] : Finishing.\n", i);
524         break;
525       case MAIN_DONE :
526         fprintf(STDERR, "THREAD[%2d] : Job is done.\n", i);
527         break;
528       }
529
530       fprintf(stderr, "Total number of suspended ... %ld\n", num_suspend);
531     }
532     sleep(1);
533   }
534
535  return 0;
536 }
537 #endif
538
539 /* Initializing routine */
540 int blas_thread_init(void){
541   BLASLONG i;
542   int ret;
543   int thread_timeout_env;
544 #ifdef NEED_STACKATTR
545   pthread_attr_t attr;
546 #endif
547
548   if (blas_server_avail) return 0;
549
550 #ifdef NEED_STACKATTR
551   pthread_attr_init(&attr);
552   pthread_attr_setguardsize(&attr,  0x1000U);
553   pthread_attr_setstacksize( &attr, 0x1000U);
554 #endif
555
556   LOCK_COMMAND(&server_lock);
557
558   if (!blas_server_avail){
559
560     thread_timeout_env=openblas_thread_timeout();
561     if (thread_timeout_env>0) {
562       if (thread_timeout_env <  4) thread_timeout_env =  4;
563       if (thread_timeout_env > 30) thread_timeout_env = 30;
564       thread_timeout = (1 << thread_timeout_env);
565     }
566
567     for(i = 0; i < blas_num_threads - 1; i++){
568
569       thread_status[i].queue  = (blas_queue_t *)NULL;
570       thread_status[i].status = THREAD_STATUS_WAKEUP;
571
572       pthread_mutex_init(&thread_status[i].lock, NULL);
573       pthread_cond_init (&thread_status[i].wakeup, NULL);
574
575 #ifdef NEED_STACKATTR
576       ret=pthread_create(&blas_threads[i], &attr,
577                      &blas_thread_server, (void *)i);
578 #else
579       ret=pthread_create(&blas_threads[i], NULL,
580                      &blas_thread_server, (void *)i);
581 #endif
582       if(ret!=0){
583         struct rlimit rlim;
584         const char *msg = strerror(ret);
585         fprintf(STDERR, "OpenBLAS blas_thread_init: pthread_create: %s\n", msg);
586 #ifdef RLIMIT_NPROC
587         if(0 == getrlimit(RLIMIT_NPROC, &rlim)) {
588           fprintf(STDERR, "OpenBLAS blas_thread_init: RLIMIT_NPROC "
589                   "%ld current, %ld max\n", (long)(rlim.rlim_cur), (long)(rlim.rlim_max));
590         }
591 #endif
592         if(0 != raise(SIGINT)) {
593           fprintf(STDERR, "OpenBLAS blas_thread_init: calling exit(3)\n");
594           exit(EXIT_FAILURE);
595         }
596       }
597     }
598
599 #ifdef MONITOR
600     pthread_create(&monitor_thread, NULL,
601                      (void *)&blas_monitor, (void *)NULL);
602 #endif
603
604     blas_server_avail = 1;
605   }
606
607   UNLOCK_COMMAND(&server_lock);
608
609   return 0;
610 }
611
612 /*
613    User can call one of two routines.
614
615      exec_blas_async ... immediately returns after jobs are queued.
616
617      exec_blas       ... returns after jobs are finished.
618 */
619
620 static BLASULONG exec_queue_lock = 0;
621
622 int exec_blas_async(BLASLONG pos, blas_queue_t *queue){
623
624 #ifdef SMP_SERVER
625   // Handle lazy re-init of the thread-pool after a POSIX fork
626   if (unlikely(blas_server_avail == 0)) blas_thread_init();
627 #endif
628   BLASLONG i = 0;
629   blas_queue_t *current = queue;
630   blas_queue_t *tsiq,*tspq;
631 #if defined(OS_LINUX) && !defined(NO_AFFINITY) && !defined(PARAMTEST)
632   int node  = get_node();
633   int nodes = get_num_nodes();
634 #endif
635
636 #ifdef SMP_DEBUG
637   int exec_count = 0;
638   fprintf(STDERR, "Exec_blas_async is called. Position = %d\n", pos);
639 #endif
640
641   blas_lock(&exec_queue_lock);
642
643     while (queue) {
644       queue -> position  = pos;
645
646 #ifdef CONSISTENT_FPCSR
647       __asm__ __volatile__ ("fnstcw %0"  : "=m" (queue -> x87_mode));
648       __asm__ __volatile__ ("stmxcsr %0" : "=m" (queue -> sse_mode));
649 #endif
650
651 #if defined(OS_LINUX) && !defined(NO_AFFINITY) && !defined(PARAMTEST)
652
653       /* Node Mapping Mode */
654
655       if (queue -> mode & BLAS_NODE) {
656
657         do {
658           while((thread_status[i].node != node || thread_status[i].queue) && (i < blas_num_threads - 1)) i ++;
659
660           if (i < blas_num_threads - 1) break;
661
662           i ++;
663           if (i >= blas_num_threads - 1) {
664             i = 0;
665             node ++;
666             if (node >= nodes) node = 0;
667           }
668
669         } while (1);
670
671       } else {
672         pthread_mutex_lock (&thread_status[i].lock);
673         tsiq = thread_status[i].queue;
674         pthread_mutex_unlock (&thread_status[i].lock);      
675         while(tsiq) {
676           i ++;
677           if (i >= blas_num_threads - 1) i = 0;
678           pthread_mutex_lock (&thread_status[i].lock);
679           tsiq = thread_status[i].queue;
680           pthread_mutex_unlock (&thread_status[i].lock);
681         }
682       }
683 #else
684       pthread_mutex_lock  (&thread_status[i].lock);
685       tsiq=thread_status[i].queue ;
686       pthread_mutex_unlock  (&thread_status[i].lock);
687       while(tsiq) {
688         i ++;
689         if (i >= blas_num_threads - 1) i = 0;
690         pthread_mutex_lock  (&thread_status[i].lock);
691         tsiq=thread_status[i].queue ;
692         pthread_mutex_unlock  (&thread_status[i].lock);
693       }
694 #endif
695
696       queue -> assigned = i;
697       WMB;
698       pthread_mutex_lock  (&thread_status[i].lock);
699       thread_status[i].queue = queue;
700       pthread_mutex_unlock  (&thread_status[i].lock);
701       WMB;
702
703       queue = queue -> next;
704       pos ++;
705 #ifdef SMP_DEBUG
706       exec_count ++;
707 #endif
708
709     }
710
711     blas_unlock(&exec_queue_lock);
712
713 #ifdef SMP_DEBUG
714     fprintf(STDERR, "Done(Number of threads = %2ld).\n", exec_count);
715 #endif
716
717     while (current) {
718
719       pos = current -> assigned;
720
721       pthread_mutex_lock  (&thread_status[pos].lock);
722       tspq=thread_status[pos].queue;
723       pthread_mutex_unlock  (&thread_status[pos].lock);
724
725       if ((BLASULONG)tspq > 1) {
726         pthread_mutex_lock  (&thread_status[pos].lock);
727
728         if (thread_status[pos].status == THREAD_STATUS_SLEEP) {
729
730
731 #ifdef MONITOR
732           num_suspend ++;
733 #endif
734
735           if (thread_status[pos].status == THREAD_STATUS_SLEEP) {
736             thread_status[pos].status = THREAD_STATUS_WAKEUP;
737             pthread_cond_signal(&thread_status[pos].wakeup);
738           }
739
740         }
741           pthread_mutex_unlock(&thread_status[pos].lock);
742       }
743
744       current = current -> next;
745     }
746
747   return 0;
748 }
749
750 int exec_blas_async_wait(BLASLONG num, blas_queue_t *queue){
751   blas_queue_t * tsqq;
752
753     while ((num > 0) && queue) {
754
755       pthread_mutex_lock(&thread_status[queue->assigned].lock);
756       tsqq=thread_status[queue -> assigned].queue;
757       pthread_mutex_unlock(&thread_status[queue->assigned].lock);
758
759
760       while(tsqq) {
761         YIELDING;
762         pthread_mutex_lock(&thread_status[queue->assigned].lock);
763         tsqq=thread_status[queue -> assigned].queue;
764         pthread_mutex_unlock(&thread_status[queue->assigned].lock);
765
766
767       };
768
769       queue = queue -> next;
770       num --;
771     }
772
773 #ifdef SMP_DEBUG
774   fprintf(STDERR, "Done.\n\n");
775 #endif
776
777   return 0;
778 }
779
780 /* Execute Threads */
781 int exec_blas(BLASLONG num, blas_queue_t *queue){
782
783 #ifdef SMP_SERVER
784   // Handle lazy re-init of the thread-pool after a POSIX fork
785   if (unlikely(blas_server_avail == 0)) blas_thread_init();
786 #endif
787   int (*routine)(blas_arg_t *, void *, void *, double *, double *, BLASLONG);
788
789 #ifdef TIMING_DEBUG
790   BLASULONG start, stop;
791 #endif
792
793   if ((num <= 0) || (queue == NULL)) return 0;
794
795 #ifdef SMP_DEBUG
796   fprintf(STDERR, "Exec_blas is called. Number of executing threads : %ld\n", num);
797 #endif
798
799 #ifdef __ELF__
800   if (omp_in_parallel && (num > 1)) {
801     if (omp_in_parallel() > 0) {
802       fprintf(stderr,
803               "OpenBLAS Warning : Detect OpenMP Loop and this application may hang. "
804               "Please rebuild the library with USE_OPENMP=1 option.\n");
805     }
806   }
807 #endif
808
809   if ((num > 1) && queue -> next) exec_blas_async(1, queue -> next);
810
811 #ifdef TIMING_DEBUG
812   start = rpcc();
813
814   fprintf(STDERR, "\n");
815 #endif
816
817   routine = queue -> routine;
818
819   if (queue -> mode & BLAS_LEGACY) {
820     legacy_exec(routine, queue -> mode, queue -> args, queue -> sb);
821   } else
822     if (queue -> mode & BLAS_PTHREAD) {
823       void (*pthreadcompat)(void *) = queue -> routine;
824       (pthreadcompat)(queue -> args);
825     } else
826       (routine)(queue -> args, queue -> range_m, queue -> range_n,
827                 queue -> sa, queue -> sb, 0);
828
829 #ifdef TIMING_DEBUG
830   stop = rpcc();
831 #endif
832
833   if ((num > 1) && queue -> next) {
834     exec_blas_async_wait(num - 1, queue -> next);
835
836     // arm: make sure results from other threads are visible
837     MB;
838   }
839
840 #ifdef TIMING_DEBUG
841   fprintf(STDERR, "Thread[0] : %16lu %16lu (%8lu cycles)\n",
842           start, stop,
843           stop - start);
844 #endif
845
846   return 0;
847 }
848
849 void goto_set_num_threads(int num_threads) {
850
851   long i;
852
853   if (num_threads < 1) num_threads = blas_num_threads;
854
855 #ifndef NO_AFFINITY
856   if (num_threads == 1) {
857     if (blas_cpu_number == 1){
858       //OpenBLAS is already single thread.
859       return;
860     }else{
861       //From multi-threads to single thread
862       //Restore the original affinity mask
863       gotoblas_set_affinity(-1);
864     }
865   }
866 #endif
867
868   if (num_threads > MAX_CPU_NUMBER) num_threads = MAX_CPU_NUMBER;
869
870   if (num_threads > blas_num_threads) {
871
872     LOCK_COMMAND(&server_lock);
873
874     increased_threads = 1;
875
876     for(i = blas_num_threads - 1; i < num_threads - 1; i++){
877
878       thread_status[i].queue  = (blas_queue_t *)NULL;
879       thread_status[i].status = THREAD_STATUS_WAKEUP;
880
881       pthread_mutex_init(&thread_status[i].lock, NULL);
882       pthread_cond_init (&thread_status[i].wakeup, NULL);
883
884 #ifdef NEED_STACKATTR
885       pthread_create(&blas_threads[i], &attr,
886                      &blas_thread_server, (void *)i);
887 #else
888       pthread_create(&blas_threads[i], NULL,
889                      &blas_thread_server, (void *)i);
890 #endif
891     }
892
893     blas_num_threads = num_threads;
894
895     UNLOCK_COMMAND(&server_lock);
896   }
897
898 #ifndef NO_AFFINITY
899   if(blas_cpu_number == 1 && num_threads > 1){
900     //Restore the thread 0 affinity.
901     gotoblas_set_affinity(0);
902   }
903 #endif
904
905   blas_cpu_number  = num_threads;
906
907 #if defined(ARCH_MIPS64)
908   //set parameters for different number of threads.
909   blas_set_parameter();
910 #endif
911
912 }
913
914 void openblas_set_num_threads(int num_threads) {
915         goto_set_num_threads(num_threads);
916
917 }
918
919 /* Compatible function with pthread_create / join */
920
921 int gotoblas_pthread(int numthreads, void *function, void *args, int stride) {
922
923   blas_queue_t queue[MAX_CPU_NUMBER];
924   int i;
925
926   if (numthreads <= 0) return 0;
927
928 #ifdef SMP
929   if (blas_cpu_number == 0) blas_get_cpu_number();
930 #ifdef SMP_SERVER
931   if (blas_server_avail == 0) blas_thread_init();
932 #endif
933 #endif
934
935   for (i = 0; i < numthreads; i ++) {
936
937     queue[i].mode    = BLAS_PTHREAD;
938     queue[i].routine = function;
939     queue[i].args    = args;
940     queue[i].range_m = NULL;
941     queue[i].range_n = NULL;
942     queue[i].sa      = args;
943     queue[i].sb      = args;
944     queue[i].next    = &queue[i + 1];
945
946     args += stride;
947   }
948
949   queue[numthreads - 1].next = NULL;
950
951   exec_blas(numthreads, queue);
952
953   return 0;
954 }
955
956 /* Shutdown procedure, but user don't have to call this routine. The */
957 /* kernel automatically kill threads.                                */
958
959 int BLASFUNC(blas_thread_shutdown)(void){
960
961   int i;
962
963   if (!blas_server_avail) return 0;
964
965   LOCK_COMMAND(&server_lock);
966
967   for (i = 0; i < blas_num_threads - 1; i++) {
968
969     pthread_mutex_lock (&thread_status[i].lock);
970
971     thread_status[i].queue = (blas_queue_t *)-1;
972
973     thread_status[i].status = THREAD_STATUS_WAKEUP;
974
975     pthread_cond_signal (&thread_status[i].wakeup);
976
977     pthread_mutex_unlock(&thread_status[i].lock);
978
979   }
980
981   for(i = 0; i < blas_num_threads - 1; i++){
982     pthread_join(blas_threads[i], NULL);
983   }
984
985   for(i = 0; i < blas_num_threads - 1; i++){
986     pthread_mutex_destroy(&thread_status[i].lock);
987     pthread_cond_destroy (&thread_status[i].wakeup);
988   }
989
990 #ifdef NEED_STACKATTR
991   pthread_attr_destory(&attr);
992 #endif
993
994   blas_server_avail = 0;
995
996   UNLOCK_COMMAND(&server_lock);
997
998   return 0;
999 }
1000
1001 #endif
1002