Fix #29084: material/texture nodes crash introduced in 2.60, execdata is being
[blender.git] / source / blender / blenlib / intern / threads.c
1 /*
2  *
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/blenlib/intern/threads.c
31  *  \ingroup bli
32  */
33
34
35 #include <errno.h>
36 #include <string.h>
37
38 #include "MEM_guardedalloc.h"
39
40
41 #include "BLI_blenlib.h"
42 #include "BLI_gsqueue.h"
43 #include "BLI_threads.h"
44
45 #include "PIL_time.h"
46
47 /* for checking system threads - BLI_system_thread_count */
48 #ifdef WIN32
49 #include "windows.h"
50 #include <sys/timeb.h>
51 #elif defined(__APPLE__)
52 #include <sys/types.h>
53 #include <sys/sysctl.h>
54 #else
55 #include <unistd.h> 
56 #include <sys/time.h>
57 #endif
58
59 #if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
60 /* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */
61 extern pthread_key_t gomp_tls_key;
62 static void *thread_tls_data;
63 #endif
64
65 /* ********** basic thread control API ************ 
66
67 Many thread cases have an X amount of jobs, and only an Y amount of
68 threads are useful (typically amount of cpus)
69
70 This code can be used to start a maximum amount of 'thread slots', which
71 then can be filled in a loop with an idle timer. 
72
73 A sample loop can look like this (pseudo c);
74
75         ListBase lb;
76         int maxthreads= 2;
77         int cont= 1;
78
79         BLI_init_threads(&lb, do_something_func, maxthreads);
80
81         while(cont) {
82                 if(BLI_available_threads(&lb) && !(escape loop event)) {
83                         // get new job (data pointer)
84                         // tag job 'processed 
85                         BLI_insert_thread(&lb, job);
86                 }
87                 else PIL_sleep_ms(50);
88                 
89                 // find if a job is ready, this the do_something_func() should write in job somewhere
90                 cont= 0;
91                 for(go over all jobs)
92                         if(job is ready) {
93                                 if(job was not removed) {
94                                         BLI_remove_thread(&lb, job);
95                                 }
96                         }
97                         else cont= 1;
98                 }
99                 // conditions to exit loop 
100                 if(if escape loop event) {
101                         if(BLI_available_threadslots(&lb)==maxthreads)
102                                 break;
103                 }
104         }
105
106         BLI_end_threads(&lb);
107
108  ************************************************ */
109 static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
110 static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;
111 static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER;
112 static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
113 static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
114 static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER;
115 static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER;
116 static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
117 static pthread_t mainid;
118 static int thread_levels= 0;    /* threads can be invoked inside threads */
119
120 /* just a max for security reasons */
121 #define RE_MAX_THREAD BLENDER_MAX_THREADS
122
123 typedef struct ThreadSlot {
124         struct ThreadSlot *next, *prev;
125         void *(*do_thread)(void *);
126         void *callerdata;
127         pthread_t pthread;
128         int avail;
129 } ThreadSlot;
130
131 static void BLI_lock_malloc_thread(void)
132 {
133         pthread_mutex_lock(&_malloc_lock);
134 }
135
136 static void BLI_unlock_malloc_thread(void)
137 {
138         pthread_mutex_unlock(&_malloc_lock);
139 }
140
141 void BLI_threadapi_init(void)
142 {
143         mainid = pthread_self();
144 }
145
146 /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)
147    problem otherwise: scene render will kill of the mutex!
148 */
149
150 void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
151 {
152         int a;
153
154         if(threadbase != NULL && tot > 0) {
155                 threadbase->first= threadbase->last= NULL;
156         
157                 if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
158                 else if(tot<1) tot= 1;
159         
160                 for(a=0; a<tot; a++) {
161                         ThreadSlot *tslot= MEM_callocN(sizeof(ThreadSlot), "threadslot");
162                         BLI_addtail(threadbase, tslot);
163                         tslot->do_thread= do_thread;
164                         tslot->avail= 1;
165                 }
166         }
167         
168         if(thread_levels == 0) {
169                 MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
170
171 #if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
172                 /* workaround for Apple gcc 4.2.1 omp vs background thread bug,
173                    we copy gomp thread local storage pointer to setting it again
174                    inside the thread that we start */
175                 thread_tls_data = pthread_getspecific(gomp_tls_key);
176 #endif
177         }
178
179         thread_levels++;
180 }
181
182 /* amount of available threads */
183 int BLI_available_threads(ListBase *threadbase)
184 {
185         ThreadSlot *tslot;
186         int counter=0;
187         
188         for(tslot= threadbase->first; tslot; tslot= tslot->next) {
189                 if(tslot->avail)
190                         counter++;
191         }
192         return counter;
193 }
194
195 /* returns thread number, for sample patterns or threadsafe tables */
196 int BLI_available_thread_index(ListBase *threadbase)
197 {
198         ThreadSlot *tslot;
199         int counter=0;
200         
201         for(tslot= threadbase->first; tslot; tslot= tslot->next, counter++) {
202                 if(tslot->avail)
203                         return counter;
204         }
205         return 0;
206 }
207
208 static void *tslot_thread_start(void *tslot_p)
209 {
210         ThreadSlot *tslot= (ThreadSlot*)tslot_p;
211
212 #if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
213         /* workaround for Apple gcc 4.2.1 omp vs background thread bug,
214            set gomp thread local storage pointer which was copied beforehand */
215         pthread_setspecific (gomp_tls_key, thread_tls_data);
216 #endif
217
218         return tslot->do_thread(tslot->callerdata);
219 }
220
221 int BLI_thread_is_main(void)
222 {
223         return pthread_equal(pthread_self(), mainid);
224 }
225
226 void BLI_insert_thread(ListBase *threadbase, void *callerdata)
227 {
228         ThreadSlot *tslot;
229         
230         for(tslot= threadbase->first; tslot; tslot= tslot->next) {
231                 if(tslot->avail) {
232                         tslot->avail= 0;
233                         tslot->callerdata= callerdata;
234                         pthread_create(&tslot->pthread, NULL, tslot_thread_start, tslot);
235                         return;
236                 }
237         }
238         printf("ERROR: could not insert thread slot\n");
239 }
240
241 void BLI_remove_thread(ListBase *threadbase, void *callerdata)
242 {
243         ThreadSlot *tslot;
244         
245         for(tslot= threadbase->first; tslot; tslot= tslot->next) {
246                 if(tslot->callerdata==callerdata) {
247                         pthread_join(tslot->pthread, NULL);
248                         tslot->callerdata= NULL;
249                         tslot->avail= 1;
250                 }
251         }
252 }
253
254 void BLI_remove_thread_index(ListBase *threadbase, int index)
255 {
256         ThreadSlot *tslot;
257         int counter=0;
258         
259         for(tslot = threadbase->first; tslot; tslot = tslot->next, counter++) {
260                 if (counter == index && tslot->avail == 0) {
261                         pthread_join(tslot->pthread, NULL);
262                         tslot->callerdata = NULL;
263                         tslot->avail = 1;
264                         break;
265                 }
266         }
267 }
268
269 void BLI_remove_threads(ListBase *threadbase)
270 {
271         ThreadSlot *tslot;
272         
273         for(tslot = threadbase->first; tslot; tslot = tslot->next) {
274                 if (tslot->avail == 0) {
275                         pthread_join(tslot->pthread, NULL);
276                         tslot->callerdata = NULL;
277                         tslot->avail = 1;
278                 }
279         }
280 }
281
282 void BLI_end_threads(ListBase *threadbase)
283 {
284         ThreadSlot *tslot;
285         
286         /* only needed if there's actually some stuff to end
287          * this way we don't end up decrementing thread_levels on an empty threadbase 
288          * */
289         if (threadbase && threadbase->first != NULL) {
290                 for(tslot= threadbase->first; tslot; tslot= tslot->next) {
291                         if(tslot->avail==0) {
292                                 pthread_join(tslot->pthread, NULL);
293                         }
294                 }
295                 BLI_freelistN(threadbase);
296         }
297
298         thread_levels--;
299         if(thread_levels==0)
300                 MEM_set_lock_callback(NULL, NULL);
301 }
302
303 /* System Information */
304
305 /* how many threads are native on this system? */
306 int BLI_system_thread_count( void )
307 {
308         int t;
309 #ifdef WIN32
310         SYSTEM_INFO info;
311         GetSystemInfo(&info);
312         t = (int) info.dwNumberOfProcessors;
313 #else 
314 #       ifdef __APPLE__
315         int mib[2];
316         size_t len;
317         
318         mib[0] = CTL_HW;
319         mib[1] = HW_NCPU;
320         len = sizeof(t);
321         sysctl(mib, 2, &t, &len, NULL, 0);
322 #       else
323         t = (int)sysconf(_SC_NPROCESSORS_ONLN);
324 #       endif
325 #endif
326         
327         if (t>RE_MAX_THREAD)
328                 return RE_MAX_THREAD;
329         if (t<1)
330                 return 1;
331         
332         return t;
333 }
334
335 /* Global Mutex Locks */
336
337 void BLI_lock_thread(int type)
338 {
339         if (type==LOCK_IMAGE)
340                 pthread_mutex_lock(&_image_lock);
341         else if (type==LOCK_PREVIEW)
342                 pthread_mutex_lock(&_preview_lock);
343         else if (type==LOCK_VIEWER)
344                 pthread_mutex_lock(&_viewer_lock);
345         else if (type==LOCK_CUSTOM1)
346                 pthread_mutex_lock(&_custom1_lock);
347         else if (type==LOCK_RCACHE)
348                 pthread_mutex_lock(&_rcache_lock);
349         else if (type==LOCK_OPENGL)
350                 pthread_mutex_lock(&_opengl_lock);
351         else if (type==LOCK_NODES)
352                 pthread_mutex_lock(&_nodes_lock);
353 }
354
355 void BLI_unlock_thread(int type)
356 {
357         if (type==LOCK_IMAGE)
358                 pthread_mutex_unlock(&_image_lock);
359         else if (type==LOCK_PREVIEW)
360                 pthread_mutex_unlock(&_preview_lock);
361         else if (type==LOCK_VIEWER)
362                 pthread_mutex_unlock(&_viewer_lock);
363         else if(type==LOCK_CUSTOM1)
364                 pthread_mutex_unlock(&_custom1_lock);
365         else if(type==LOCK_RCACHE)
366                 pthread_mutex_unlock(&_rcache_lock);
367         else if(type==LOCK_OPENGL)
368                 pthread_mutex_unlock(&_opengl_lock);
369         else if(type==LOCK_NODES)
370                 pthread_mutex_unlock(&_nodes_lock);
371 }
372
373 /* Mutex Locks */
374
375 void BLI_mutex_init(ThreadMutex *mutex)
376 {
377         pthread_mutex_init(mutex, NULL);
378 }
379
380 void BLI_mutex_lock(ThreadMutex *mutex)
381 {
382         pthread_mutex_lock(mutex);
383 }
384
385 void BLI_mutex_unlock(ThreadMutex *mutex)
386 {
387         pthread_mutex_unlock(mutex);
388 }
389
390 void BLI_mutex_end(ThreadMutex *mutex)
391 {
392         pthread_mutex_destroy(mutex);
393 }
394
395 /* Read/Write Mutex Lock */
396
397 void BLI_rw_mutex_init(ThreadRWMutex *mutex)
398 {
399         pthread_rwlock_init(mutex, NULL);
400 }
401
402 void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
403 {
404         if(mode == THREAD_LOCK_READ)
405                 pthread_rwlock_rdlock(mutex);
406         else
407                 pthread_rwlock_wrlock(mutex);
408 }
409
410 void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
411 {
412         pthread_rwlock_unlock(mutex);
413 }
414
415 void BLI_rw_mutex_end(ThreadRWMutex *mutex)
416 {
417         pthread_rwlock_destroy(mutex);
418 }
419
420 /* ************************************************ */
421
422 typedef struct ThreadedWorker {
423         ListBase threadbase;
424         void *(*work_fnct)(void *);
425         char     busy[RE_MAX_THREAD];
426         int              total;
427         int              sleep_time;
428 } ThreadedWorker;
429
430 typedef struct WorkParam {
431         ThreadedWorker *worker;
432         void *param;
433         int       index;
434 } WorkParam;
435
436 static void *exec_work_fnct(void *v_param)
437 {
438         WorkParam *p = (WorkParam*)v_param;
439         void *value;
440         
441         value = p->worker->work_fnct(p->param);
442         
443         p->worker->busy[p->index] = 0;
444         MEM_freeN(p);
445         
446         return value;
447 }
448
449 ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time)
450 {
451         ThreadedWorker *worker;
452         
453         (void)sleep_time; /* unused */
454         
455         worker = MEM_callocN(sizeof(ThreadedWorker), "threadedworker");
456         
457         if (tot > RE_MAX_THREAD)
458         {
459                 tot = RE_MAX_THREAD;
460         }
461         else if (tot < 1)
462         {
463                 tot= 1;
464         }
465         
466         worker->total = tot;
467         worker->work_fnct = do_thread;
468         
469         BLI_init_threads(&worker->threadbase, exec_work_fnct, tot);
470         
471         return worker;
472 }
473
474 void BLI_end_worker(ThreadedWorker *worker)
475 {
476         BLI_remove_threads(&worker->threadbase);
477 }
478
479 void BLI_destroy_worker(ThreadedWorker *worker)
480 {
481         BLI_end_worker(worker);
482         BLI_freelistN(&worker->threadbase);
483         MEM_freeN(worker);
484 }
485
486 void BLI_insert_work(ThreadedWorker *worker, void *param)
487 {
488         WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam");
489         int index;
490         
491         if (BLI_available_threads(&worker->threadbase) == 0)
492         {
493                 index = worker->total;
494                 while(index == worker->total)
495                 {
496                         PIL_sleep_ms(worker->sleep_time);
497                         
498                         for (index = 0; index < worker->total; index++)
499                         {
500                                 if (worker->busy[index] == 0)
501                                 {
502                                         BLI_remove_thread_index(&worker->threadbase, index);
503                                         break;
504                                 }
505                         }
506                 }
507         }
508         else
509         {
510                 index = BLI_available_thread_index(&worker->threadbase);
511         }
512         
513         worker->busy[index] = 1;
514         
515         p->param = param;
516         p->index = index;
517         p->worker = worker;
518         
519         BLI_insert_thread(&worker->threadbase, p);
520 }
521
522 /* ************************************************ */
523
524 struct ThreadQueue {
525         GSQueue *queue;
526         pthread_mutex_t mutex;
527         pthread_cond_t cond;
528         int nowait;
529 };
530
531 ThreadQueue *BLI_thread_queue_init(void)
532 {
533         ThreadQueue *queue;
534
535         queue= MEM_callocN(sizeof(ThreadQueue), "ThreadQueue");
536         queue->queue= BLI_gsqueue_new(sizeof(void*));
537
538         pthread_mutex_init(&queue->mutex, NULL);
539         pthread_cond_init(&queue->cond, NULL);
540
541         return queue;
542 }
543
544 void BLI_thread_queue_free(ThreadQueue *queue)
545 {
546         pthread_cond_destroy(&queue->cond);
547         pthread_mutex_destroy(&queue->mutex);
548
549         BLI_gsqueue_free(queue->queue);
550
551         MEM_freeN(queue);
552 }
553
554 void BLI_thread_queue_push(ThreadQueue *queue, void *work)
555 {
556         pthread_mutex_lock(&queue->mutex);
557
558         BLI_gsqueue_push(queue->queue, &work);
559
560         /* signal threads waiting to pop */
561         pthread_cond_signal(&queue->cond);
562         pthread_mutex_unlock(&queue->mutex);
563 }
564
565 void *BLI_thread_queue_pop(ThreadQueue *queue)
566 {
567         void *work= NULL;
568
569         /* wait until there is work */
570         pthread_mutex_lock(&queue->mutex);
571         while(BLI_gsqueue_is_empty(queue->queue) && !queue->nowait)
572                 pthread_cond_wait(&queue->cond, &queue->mutex);
573
574         /* if we have something, pop it */
575         if(!BLI_gsqueue_is_empty(queue->queue))
576                 BLI_gsqueue_pop(queue->queue, &work);
577
578         pthread_mutex_unlock(&queue->mutex);
579
580         return work;
581 }
582
583 static void wait_timeout(struct timespec *timeout, int ms)
584 {
585         ldiv_t div_result;
586         long sec, usec, x;
587
588 #ifdef WIN32
589         {
590                 struct _timeb now;
591                 _ftime(&now);
592                 sec = now.time;
593                 usec = now.millitm*1000; /* microsecond precision would be better */
594         }
595 #else
596         {
597                 struct timeval now;
598                 gettimeofday(&now, NULL);
599                 sec = now.tv_sec;
600                 usec = now.tv_usec;
601         }
602 #endif
603
604         /* add current time + millisecond offset */
605         div_result = ldiv(ms, 1000);
606         timeout->tv_sec = sec + div_result.quot;
607
608         x = usec + (div_result.rem*1000);
609
610         if (x >= 1000000) {
611                 timeout->tv_sec++;
612                 x -= 1000000;
613         }
614
615         timeout->tv_nsec = x*1000;
616 }
617
618 void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)
619 {
620         double t;
621         void *work= NULL;
622         struct timespec timeout;
623
624         t= PIL_check_seconds_timer();
625         wait_timeout(&timeout, ms);
626
627         /* wait until there is work */
628         pthread_mutex_lock(&queue->mutex);
629         while(BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) {
630                 if(pthread_cond_timedwait(&queue->cond, &queue->mutex, &timeout) == ETIMEDOUT)
631                         break;
632                 else if(PIL_check_seconds_timer() - t >= ms*0.001)
633                         break;
634         }
635
636         /* if we have something, pop it */
637         if(!BLI_gsqueue_is_empty(queue->queue))
638                 BLI_gsqueue_pop(queue->queue, &work);
639
640         pthread_mutex_unlock(&queue->mutex);
641
642         return work;
643 }
644
645 int BLI_thread_queue_size(ThreadQueue *queue)
646 {
647         int size;
648
649         pthread_mutex_lock(&queue->mutex);
650         size= BLI_gsqueue_size(queue->queue);
651         pthread_mutex_unlock(&queue->mutex);
652
653         return size;
654 }
655
656 void BLI_thread_queue_nowait(ThreadQueue *queue)
657 {
658         pthread_mutex_lock(&queue->mutex);
659
660         queue->nowait= 1;
661
662         /* signal threads waiting to pop */
663         pthread_cond_signal(&queue->cond);
664         pthread_mutex_unlock(&queue->mutex);
665 }
666