<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>




<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document"><title>jpeg editor</title>

<style>
<!--
	table td.head{ 
		background-color: #3a6ba5;
		border: 1px #000000 solid;
		font-family: Verdana;
		font-weight: bold;
		font-size: 14px;
		color: #f79c19;
		padding: 6px;
	}

	table td.body{ 
		border-bottom: 1px #6699CC dotted;
		text-align: left;
		font-family: Verdana, sans-serif, Arial;
		font-weight: normal;
		font-size: 14px;
		color: #3A6BA5;
		background-color: #fafafa;
		padding: 6px;
	}
	
-->
</style></head><body>



<p align="left"><font color="#ff0000" size="6"><span lang="en-ca"><b>&nbsp; 
 
</b></span><b>&nbsp;&nbsp;&nbsp; <span lang="en-ca">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Try to use CPU affinity to allow threads to run in different CPU<br>
</span></b></font></p>
  <b><font color="#ff0000" size="5"><span lang="en-ca"></span><span lang="en-ca">The problem</span></font></b><div align="left">This
is a FAKE problem as it is not necessary! I tried to add this feature
into blender to allow it really use all my 6 cores of AMD 1055T instead
of always consumes 100% of single cpu. However, this is a wrong
assumption that ubuntu cannot achieve multi-core usage for
multi-threads. It is only because my BIOS of mother board is too old
that cause OS not be able to recognize CPU model. However, it shows one
possibility to achieve this by programming.<br>
See the colored part, you need to define an important macro to allow compilation! (__USE_GNU, _GNU_SOURCE , WITH_CPUAFFINITY)<br>
<span style="font-weight: bold;"></span></div><br><p>/*<br>
&nbsp;*<br>
&nbsp;* $Id: threads.c 35246 2011-02-27 20:37:56Z jesterking $<br>
&nbsp;*<br>
&nbsp;* ***** BEGIN GPL LICENSE BLOCK *****<br>
&nbsp;*<br>
&nbsp;* This program is free software; you can redistribute it and/or<br>
&nbsp;* modify it under the terms of the GNU General Public License<br>
&nbsp;* as published by the Free Software Foundation; either version 2<br>
&nbsp;* of the License, or (at your option) any later version.<br>
&nbsp;*<br>
&nbsp;* This program is distributed in the hope that it will be useful,<br>
&nbsp;* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
&nbsp;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&nbsp; See the<br>
&nbsp;* GNU General Public License for more details.<br>
&nbsp;*<br>
&nbsp;* You should have received a copy of the GNU General Public License<br>
&nbsp;* along with this program; if not, write to the Free Software Foundation,<br>
&nbsp;* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br>
&nbsp;*<br>
&nbsp;* The Original Code is Copyright (C) 2006 Blender Foundation<br>
&nbsp;* All rights reserved.<br>
&nbsp;*<br>
&nbsp;* The Original Code is: all of this file.<br>
&nbsp;*<br>
&nbsp;* Contributor(s): none yet.<br>
&nbsp;*<br>
&nbsp;* ***** END GPL LICENSE BLOCK *****<br>
&nbsp;*/<br>
<br>
/** \file blender/blenlib/intern/threads.c<br>
&nbsp;*&nbsp; \ingroup bli<br>
&nbsp;*/<br>
<br>
<br>
#include &lt;errno.h&gt;<br>
#include &lt;string.h&gt;<br>
<br>
#include "MEM_guardedalloc.h"<br>
<br>
<br>
#include "BLI_blenlib.h"<br>
#include "BLI_gsqueue.h"<br>
#include "BLI_threads.h"<br>
<br>
#include "PIL_time.h"<br>
<br>
/* for checking system threads - BLI_system_thread_count */<br>
#ifdef WIN32<br>
#include "windows.h"<br>
#include &lt;sys/timeb.h&gt;<br>
#elif defined(__APPLE__)<br>
#include &lt;sys/types.h&gt;<br>
#include &lt;sys/sysctl.h&gt;<br>
#else<br>
#include &lt;unistd.h&gt;<br>
#include &lt;sys/time.h&gt;<br>
// added for cpu affinity<br>
<br>
<br>
<span style="background-color: rgb(153, 153, 255);">#ifdef WITH_CPUAFFINITY</span><br style="background-color: rgb(153, 153, 255);">
<br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#include &lt;sys/sysinfo.h&gt;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#include &lt;pthread.h&gt;</span><br style="background-color: rgb(153, 153, 255);">
<br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#include &lt;sched.h&gt;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#include &lt;ctype.h&gt;</span><br style="background-color: rgb(153, 153, 255);">
<br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#endif //WITH_CPUAFFINITY</span><br>
<br>
#endif<br>
<br>
#if defined(__APPLE__) &amp;&amp; (PARALLEL == 1) &amp;&amp; (__GNUC__ == 4) &amp;&amp; (__GNUC_MINOR__ == 2)<br>
/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */<br>
extern pthread_key_t gomp_tls_key;<br>
static void *thread_tls_data;<br>
#endif<br>
<br>
/* ********** basic thread control API ************<br>
<br>
Many thread cases have an X amount of jobs, and only an Y amount of<br>
threads are useful (typically amount of cpus)<br>
<br>
This code can be used to start a maximum amount of 'thread slots', which<br>
then can be filled in a loop with an idle timer.<br>
<br>
A sample loop can look like this (pseudo c);<br>
<br>
&nbsp;&nbsp;&nbsp; ListBase lb;<br>
&nbsp;&nbsp;&nbsp; int maxthreads= 2;<br>
&nbsp;&nbsp;&nbsp; int cont= 1;<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_init_threads(&amp;lb, do_something_func, maxthreads);<br>
<br>
&nbsp;&nbsp;&nbsp; while(cont) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(BLI_available_threads(&amp;lb) &amp;&amp; !(escape loop event)) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // get new job (data pointer)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // tag job 'processed<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_insert_thread(&amp;lb, job);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else PIL_sleep_ms(50);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // find if a job is ready, this the do_something_func() should write in job somewhere<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cont= 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(go over all jobs)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(job is ready) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(job was not removed) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_remove_thread(&amp;lb, job);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else cont= 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // conditions to exit loop<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(if escape loop event) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(BLI_available_threadslots(&amp;lb)==maxthreads)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_end_threads(&amp;lb);<br>
<br>
&nbsp;************************************************ */<br>
static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER;<br>
static pthread_t mainid;<br>
static int thread_levels= 0;&nbsp;&nbsp;&nbsp; /* threads can be invoked inside threads */<br>
<br>
/* just a max for security reasons */<br>
#define RE_MAX_THREAD BLENDER_MAX_THREADS<br>
<br>
typedef struct ThreadSlot {<br>
&nbsp;&nbsp;&nbsp; struct ThreadSlot *next, *prev;<br>
&nbsp;&nbsp;&nbsp; void *(*do_thread)(void *);<br>
&nbsp;&nbsp;&nbsp; void *callerdata;<br>
&nbsp;&nbsp;&nbsp; pthread_t pthread;<br>
&nbsp;&nbsp;&nbsp; int avail;<br>
} ThreadSlot;<br>
<br>
static void BLI_lock_malloc_thread(void)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_malloc_lock);<br>
}<br>
<br>
static void BLI_unlock_malloc_thread(void)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_malloc_lock);<br>
}<br>
<br>
void BLI_threadapi_init(void)<br>
{<br>
&nbsp;&nbsp;&nbsp; mainid = pthread_self();<br>
}<br>
<br>
/* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)<br>
&nbsp;&nbsp; problem otherwise: scene render will kill of the mutex!<br>
*/<br>
<br>
void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)<br>
{<br>
&nbsp;&nbsp;&nbsp; int a;<br>
<br>
&nbsp;&nbsp;&nbsp; if(threadbase != NULL &amp;&amp; tot &gt; 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; threadbase-&gt;first= threadbase-&gt;last= NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tot&gt;RE_MAX_THREAD) tot= RE_MAX_THREAD;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(tot&lt;1) tot= 1;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(a=0; a&lt;tot; a++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ThreadSlot *tslot= MEM_callocN(sizeof(ThreadSlot), "threadslot");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_addtail(threadbase, tslot);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;do_thread= do_thread;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;avail= 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if(thread_levels == 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);<br>
<br>
#if defined(__APPLE__) &amp;&amp; (PARALLEL == 1) &amp;&amp; (__GNUC__ == 4) &amp;&amp; (__GNUC_MINOR__ == 2)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* workaround for Apple gcc 4.2.1 omp vs background thread bug,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; we copy gomp thread local storage pointer to setting it again<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; inside the thread that we start */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; thread_tls_data = pthread_getspecific(gomp_tls_key);<br>
#endif<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; thread_levels++;<br>
}<br>
<br>
/* amount of available threads */<br>
int BLI_available_threads(ListBase *threadbase)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
&nbsp;&nbsp;&nbsp; int counter=0;<br>
<br>
&nbsp;&nbsp;&nbsp; for(tslot= threadbase-&gt;first; tslot; tslot= tslot-&gt;next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tslot-&gt;avail)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; counter++;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; return counter;<br>
}<br>
<br>
/* returns thread number, for sample patterns or threadsafe tables */<br>
int BLI_available_thread_index(ListBase *threadbase)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
&nbsp;&nbsp;&nbsp; int counter=0;<br>
<br>
&nbsp;&nbsp;&nbsp; for(tslot= threadbase-&gt;first; tslot; tslot= tslot-&gt;next, counter++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tslot-&gt;avail)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return counter;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
static void *tslot_thread_start(void *tslot_p)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot= (ThreadSlot*)tslot_p;<br>
<br>
#if defined(__APPLE__) &amp;&amp; (PARALLEL == 1) &amp;&amp; (__GNUC__ == 4) &amp;&amp; (__GNUC_MINOR__ == 2)<br>
&nbsp;&nbsp;&nbsp; /* workaround for Apple gcc 4.2.1 omp vs background thread bug,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; set gomp thread local storage pointer which was copied beforehand */<br>
&nbsp;&nbsp;&nbsp; pthread_setspecific (gomp_tls_key, thread_tls_data);<br>
#endif<br>
<br>
&nbsp;&nbsp;&nbsp; return tslot-&gt;do_thread(tslot-&gt;callerdata);<br>
}<br>
<br>
int BLI_thread_is_main(void) {<br>
&nbsp;&nbsp;&nbsp; return pthread_equal(pthread_self(), mainid);<br>
}<br>
<br>
void debugThread(pthread_t pt)<br>
{<br>
&nbsp;&nbsp;&nbsp; int policy = 0;<br>
&nbsp;&nbsp;&nbsp; struct sched_param param;<br>
&nbsp;&nbsp;&nbsp; if (pthread_getschedparam(pt, &amp;policy, &amp;param) == 0)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("policy=%d and param=%d\n", policy, param.__sched_priority);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; printf("concurrency=%d\n", pthread_getconcurrency());<br>
<br>
}<br>
<br>
void BLI_insert_thread(ListBase *threadbase, void *callerdata)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
<span style="background-color: rgb(153, 153, 255);">#ifdef WITH_CPUAFFINITY</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; // we want to aggressavely allocate thread to occupy all cpu's</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; // so, we want to see which cpu has been used by our threads</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; cpu_set_t cpuMask;&nbsp; //</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; cpu_set_t cpuUsed;&nbsp;&nbsp; //</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; static int maxCPU = 0;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; // initialized once for all</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; if (maxCPU == 0)</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxCPU = BLI_system_thread_count();</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; CPU_ZERO(&amp;cpuUsed);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#endif</span><br>
&nbsp;&nbsp;&nbsp; for(tslot= threadbase-&gt;first; tslot; tslot= tslot-&gt;next)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tslot-&gt;avail)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;avail= 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;callerdata= callerdata;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
pthread_create(&amp;tslot-&gt;pthread, NULL, tslot_thread_start, tslot);<br>
<br>
<span style="background-color: rgb(153, 153, 255);">#ifdef WITH_CPUAFFINITY</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t i;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// if we cannot find available cpu, then we don't set affinity as it
won't matter,</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // just let OS to handle threads.</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("debug: about to set thread affinity...\n");</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( i = 0; i &lt; maxCPU; i ++)</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!(CPU_ISSET(i, &amp;cpuUsed)))</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// we find a free one and set affinity</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
CPU_ZERO(&amp;cpuMask);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
CPU_SET(i, &amp;cpuMask);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// if it fails, we lose nothing as it is just an enhancement to better
use all cpu power</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (pthread_setaffinity_np(tslot-&gt;pthread, sizeof(cpu_set_t),
&amp;cpuMask)!= 0)</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
printf("WARNING: set cpu affinity failed!\n");</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
printf("debug: set cpu affinity successful for processor %d\n", i);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#endif</span><br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
<span style="background-color: rgb(153, 153, 255);">#ifdef WITH_CPUAFFINITY</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CPU_ZERO(&amp;cpuMask);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int res = 0;</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((res =
pthread_getaffinity_np(tslot-&gt;pthread, sizeof(cpuMask),
&amp;cpuMask)) == 0)</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
CPU_OR(&amp;cpuUsed, &amp;cpuUsed, &amp;cpuMask);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
printf("debug: get cpu affinity failed with %d\n", res);</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="background-color: rgb(153, 153, 255);">
<span style="background-color: rgb(153, 153, 255);">#endif</span><br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //else if we
failed, we don't even care cause we will use default 0 to allocate
thread<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; printf("ERROR: could not insert thread slot\n");<br>
}<br>
<br>
void BLI_remove_thread(ListBase *threadbase, void *callerdata)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
<br>
&nbsp;&nbsp;&nbsp; for(tslot= threadbase-&gt;first; tslot; tslot= tslot-&gt;next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tslot-&gt;callerdata==callerdata) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_join(tslot-&gt;pthread, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;callerdata= NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;avail= 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
void BLI_remove_thread_index(ListBase *threadbase, int index)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
&nbsp;&nbsp;&nbsp; int counter=0;<br>
<br>
&nbsp;&nbsp;&nbsp; for(tslot = threadbase-&gt;first; tslot; tslot = tslot-&gt;next, counter++) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (counter == index &amp;&amp; tslot-&gt;avail == 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_join(tslot-&gt;pthread, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;callerdata = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;avail = 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
void BLI_remove_threads(ListBase *threadbase)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
<br>
&nbsp;&nbsp;&nbsp; for(tslot = threadbase-&gt;first; tslot; tslot = tslot-&gt;next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (tslot-&gt;avail == 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_join(tslot-&gt;pthread, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;callerdata = NULL;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tslot-&gt;avail = 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
<br>
void BLI_end_threads(ListBase *threadbase)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadSlot *tslot;<br>
<br>
&nbsp;&nbsp;&nbsp; /* only needed if there's actually some stuff to end<br>
&nbsp;&nbsp;&nbsp; &nbsp;* this way we don't end up decrementing thread_levels on an empty threadbase<br>
&nbsp;&nbsp;&nbsp; &nbsp;* */<br>
&nbsp;&nbsp;&nbsp; if (threadbase &amp;&amp; threadbase-&gt;first != NULL) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(tslot= threadbase-&gt;first; tslot; tslot= tslot-&gt;next) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(tslot-&gt;avail==0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_join(tslot-&gt;pthread, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_freelistN(threadbase);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; thread_levels--;<br>
&nbsp;&nbsp;&nbsp; if(thread_levels==0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MEM_set_lock_callback(NULL, NULL);<br>
}<br>
<br>
/* System Information */<br>
<br>
/* how many threads are native on this system? */<br>
int BLI_system_thread_count( void )<br>
{<br>
&nbsp;&nbsp;&nbsp; int t;<br>
#ifdef WIN32<br>
&nbsp;&nbsp;&nbsp; SYSTEM_INFO info;<br>
&nbsp;&nbsp;&nbsp; GetSystemInfo(&amp;info);<br>
&nbsp;&nbsp;&nbsp; t = (int) info.dwNumberOfProcessors;<br>
#else<br>
#&nbsp;&nbsp;&nbsp; ifdef __APPLE__<br>
&nbsp;&nbsp;&nbsp; int mib[2];<br>
&nbsp;&nbsp;&nbsp; size_t len;<br>
<br>
&nbsp;&nbsp;&nbsp; mib[0] = CTL_HW;<br>
&nbsp;&nbsp;&nbsp; mib[1] = HW_NCPU;<br>
&nbsp;&nbsp;&nbsp; len = sizeof(t);<br>
&nbsp;&nbsp;&nbsp; sysctl(mib, 2, &amp;t, &amp;len, NULL, 0);<br>
#&nbsp;&nbsp;&nbsp; elif defined(__sgi)<br>
&nbsp;&nbsp;&nbsp; t = sysconf(_SC_NPROC_ONLN);<br>
#&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; t = (int)sysconf(_SC_NPROCESSORS_ONLN);<br>
#&nbsp;&nbsp;&nbsp; endif<br>
#endif<br>
<br>
&nbsp;&nbsp;&nbsp; if (t&gt;RE_MAX_THREAD)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return RE_MAX_THREAD;<br>
&nbsp;&nbsp;&nbsp; if (t&lt;1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
<br>
&nbsp;&nbsp;&nbsp; return t;<br>
}<br>
<br>
/* Global Mutex Locks */<br>
<br>
void BLI_lock_thread(int type)<br>
{<br>
&nbsp;&nbsp;&nbsp; if (type==LOCK_IMAGE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_image_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_PREVIEW)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_preview_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_VIEWER)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_viewer_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_CUSTOM1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_custom1_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_RCACHE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_rcache_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_OPENGL)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;_opengl_lock);<br>
}<br>
<br>
void BLI_unlock_thread(int type)<br>
{<br>
&nbsp;&nbsp;&nbsp; if (type==LOCK_IMAGE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_image_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_PREVIEW)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_preview_lock);<br>
&nbsp;&nbsp;&nbsp; else if (type==LOCK_VIEWER)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_viewer_lock);<br>
&nbsp;&nbsp;&nbsp; else if(type==LOCK_CUSTOM1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_custom1_lock);<br>
&nbsp;&nbsp;&nbsp; else if(type==LOCK_RCACHE)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_rcache_lock);<br>
&nbsp;&nbsp;&nbsp; else if(type==LOCK_OPENGL)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;_opengl_lock);<br>
}<br>
<br>
/* Mutex Locks */<br>
<br>
void BLI_mutex_init(ThreadMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_init(mutex, NULL);<br>
}<br>
<br>
void BLI_mutex_lock(ThreadMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(mutex);<br>
}<br>
<br>
void BLI_mutex_unlock(ThreadMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(mutex);<br>
}<br>
<br>
void BLI_mutex_end(ThreadMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_destroy(mutex);<br>
}<br>
<br>
/* Read/Write Mutex Lock */<br>
<br>
void BLI_rw_mutex_init(ThreadRWMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_rwlock_init(mutex, NULL);<br>
}<br>
<br>
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)<br>
{<br>
&nbsp;&nbsp;&nbsp; if(mode == THREAD_LOCK_READ)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_rwlock_rdlock(mutex);<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_rwlock_wrlock(mutex);<br>
}<br>
<br>
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_rwlock_unlock(mutex);<br>
}<br>
<br>
void BLI_rw_mutex_end(ThreadRWMutex *mutex)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_rwlock_destroy(mutex);<br>
}<br>
<br>
/* ************************************************ */<br>
<br>
typedef struct ThreadedWorker {<br>
&nbsp;&nbsp;&nbsp; ListBase threadbase;<br>
&nbsp;&nbsp;&nbsp; void *(*work_fnct)(void *);<br>
&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp; &nbsp;busy[RE_MAX_THREAD];<br>
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;total;<br>
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;sleep_time;<br>
} ThreadedWorker;<br>
<br>
typedef struct WorkParam {<br>
&nbsp;&nbsp;&nbsp; ThreadedWorker *worker;<br>
&nbsp;&nbsp;&nbsp; void *param;<br>
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp; &nbsp; index;<br>
} WorkParam;<br>
<br>
static void *exec_work_fnct(void *v_param)<br>
{<br>
&nbsp;&nbsp;&nbsp; WorkParam *p = (WorkParam*)v_param;<br>
&nbsp;&nbsp;&nbsp; void *value;<br>
<br>
&nbsp;&nbsp;&nbsp; value = p-&gt;worker-&gt;work_fnct(p-&gt;param);<br>
<br>
&nbsp;&nbsp;&nbsp; p-&gt;worker-&gt;busy[p-&gt;index] = 0;<br>
&nbsp;&nbsp;&nbsp; MEM_freeN(p);<br>
<br>
&nbsp;&nbsp;&nbsp; return value;<br>
}<br>
<br>
ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadedWorker *worker;<br>
<br>
&nbsp;&nbsp;&nbsp; (void)sleep_time; /* unused */<br>
<br>
&nbsp;&nbsp;&nbsp; worker = MEM_callocN(sizeof(ThreadedWorker), "threadedworker");<br>
<br>
&nbsp;&nbsp;&nbsp; if (tot &gt; RE_MAX_THREAD)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tot = RE_MAX_THREAD;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else if (tot &lt; 1)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tot= 1;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; worker-&gt;total = tot;<br>
&nbsp;&nbsp;&nbsp; worker-&gt;work_fnct = do_thread;<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_init_threads(&amp;worker-&gt;threadbase, exec_work_fnct, tot);<br>
<br>
&nbsp;&nbsp;&nbsp; return worker;<br>
}<br>
<br>
void BLI_end_worker(ThreadedWorker *worker)<br>
{<br>
&nbsp;&nbsp;&nbsp; BLI_remove_threads(&amp;worker-&gt;threadbase);<br>
}<br>
<br>
void BLI_destroy_worker(ThreadedWorker *worker)<br>
{<br>
&nbsp;&nbsp;&nbsp; BLI_end_worker(worker);<br>
&nbsp;&nbsp;&nbsp; BLI_freelistN(&amp;worker-&gt;threadbase);<br>
&nbsp;&nbsp;&nbsp; MEM_freeN(worker);<br>
}<br>
<br>
void BLI_insert_work(ThreadedWorker *worker, void *param)<br>
{<br>
&nbsp;&nbsp;&nbsp; WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam");<br>
&nbsp;&nbsp;&nbsp; int index;<br>
<br>
&nbsp;&nbsp;&nbsp; if (BLI_available_threads(&amp;worker-&gt;threadbase) == 0)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index = worker-&gt;total;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while(index == worker-&gt;total)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PIL_sleep_ms(worker-&gt;sleep_time);<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (index = 0; index &lt; worker-&gt;total; index++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (worker-&gt;busy[index] == 0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
BLI_remove_thread_index(&amp;worker-&gt;threadbase, index);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index = BLI_available_thread_index(&amp;worker-&gt;threadbase);<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; worker-&gt;busy[index] = 1;<br>
<br>
&nbsp;&nbsp;&nbsp; p-&gt;param = param;<br>
&nbsp;&nbsp;&nbsp; p-&gt;index = index;<br>
&nbsp;&nbsp;&nbsp; p-&gt;worker = worker;<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_insert_thread(&amp;worker-&gt;threadbase, p);<br>
}<br>
<br>
/* ************************************************ */<br>
<br>
struct ThreadQueue {<br>
&nbsp;&nbsp;&nbsp; GSQueue *queue;<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_t mutex;<br>
&nbsp;&nbsp;&nbsp; pthread_cond_t cond;<br>
&nbsp;&nbsp;&nbsp; int nowait;<br>
};<br>
<br>
ThreadQueue *BLI_thread_queue_init(void)<br>
{<br>
&nbsp;&nbsp;&nbsp; ThreadQueue *queue;<br>
<br>
&nbsp;&nbsp;&nbsp; queue= MEM_callocN(sizeof(ThreadQueue), "ThreadQueue");<br>
&nbsp;&nbsp;&nbsp; queue-&gt;queue= BLI_gsqueue_new(sizeof(void*));<br>
<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_init(&amp;queue-&gt;mutex, NULL);<br>
&nbsp;&nbsp;&nbsp; pthread_cond_init(&amp;queue-&gt;cond, NULL);<br>
<br>
&nbsp;&nbsp;&nbsp; return queue;<br>
}<br>
<br>
void BLI_thread_queue_free(ThreadQueue *queue)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_cond_destroy(&amp;queue-&gt;cond);<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_destroy(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_gsqueue_free(queue-&gt;queue);<br>
<br>
&nbsp;&nbsp;&nbsp; MEM_freeN(queue);<br>
}<br>
<br>
void BLI_thread_queue_push(ThreadQueue *queue, void *work)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; BLI_gsqueue_push(queue-&gt;queue, &amp;work);<br>
<br>
&nbsp;&nbsp;&nbsp; /* signal threads waiting to pop */<br>
&nbsp;&nbsp;&nbsp; pthread_cond_signal(&amp;queue-&gt;cond);<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;queue-&gt;mutex);<br>
}<br>
<br>
void *BLI_thread_queue_pop(ThreadQueue *queue)<br>
{<br>
&nbsp;&nbsp;&nbsp; void *work= NULL;<br>
<br>
&nbsp;&nbsp;&nbsp; /* wait until there is work */<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;queue-&gt;mutex);<br>
&nbsp;&nbsp;&nbsp; while(BLI_gsqueue_is_empty(queue-&gt;queue) &amp;&amp; !queue-&gt;nowait)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pthread_cond_wait(&amp;queue-&gt;cond, &amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; /* if we have something, pop it */<br>
&nbsp;&nbsp;&nbsp; if(!BLI_gsqueue_is_empty(queue-&gt;queue))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_gsqueue_pop(queue-&gt;queue, &amp;work);<br>
<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; return work;<br>
}<br>
<br>
static void wait_timeout(struct timespec *timeout, int ms)<br>
{<br>
&nbsp;&nbsp;&nbsp; ldiv_t div_result;<br>
&nbsp;&nbsp;&nbsp; long sec, usec, x;<br>
<br>
#ifdef WIN32<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct _timeb now;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _ftime(&amp;now);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sec = now.time;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; usec = now.millitm*1000; /* microsecond precision would be better */<br>
&nbsp;&nbsp;&nbsp; }<br>
#else<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct timeval now;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; gettimeofday(&amp;now, NULL);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sec = now.tv_sec;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; usec = now.tv_usec;<br>
&nbsp;&nbsp;&nbsp; }<br>
#endif<br>
<br>
&nbsp;&nbsp;&nbsp; /* add current time + millisecond offset */<br>
&nbsp;&nbsp;&nbsp; div_result = ldiv(ms, 1000);<br>
&nbsp;&nbsp;&nbsp; timeout-&gt;tv_sec = sec + div_result.quot;<br>
<br>
&nbsp;&nbsp;&nbsp; x = usec + (div_result.rem*1000);<br>
<br>
&nbsp;&nbsp;&nbsp; if (x &gt;= 1000000) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; timeout-&gt;tv_sec++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; x -= 1000000;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; timeout-&gt;tv_nsec = x*1000;<br>
}<br>
<br>
void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms)<br>
{<br>
&nbsp;&nbsp;&nbsp; double t;<br>
&nbsp;&nbsp;&nbsp; void *work= NULL;<br>
&nbsp;&nbsp;&nbsp; struct timespec timeout;<br>
<br>
&nbsp;&nbsp;&nbsp; t= PIL_check_seconds_timer();<br>
&nbsp;&nbsp;&nbsp; wait_timeout(&amp;timeout, ms);<br>
<br>
&nbsp;&nbsp;&nbsp; /* wait until there is work */<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;queue-&gt;mutex);<br>
&nbsp;&nbsp;&nbsp; while(BLI_gsqueue_is_empty(queue-&gt;queue) &amp;&amp; !queue-&gt;nowait) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if(pthread_cond_timedwait(&amp;queue-&gt;cond, &amp;queue-&gt;mutex,
&amp;timeout) == ETIMEDOUT)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(PIL_check_seconds_timer() - t &gt;= ms*0.001)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; /* if we have something, pop it */<br>
&nbsp;&nbsp;&nbsp; if(!BLI_gsqueue_is_empty(queue-&gt;queue))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BLI_gsqueue_pop(queue-&gt;queue, &amp;work);<br>
<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; return work;<br>
}<br>
<br>
int BLI_thread_queue_size(ThreadQueue *queue)<br>
{<br>
&nbsp;&nbsp;&nbsp; int size;<br>
<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;queue-&gt;mutex);<br>
&nbsp;&nbsp;&nbsp; size= BLI_gsqueue_size(queue-&gt;queue);<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; return size;<br>
}<br>
<br>
void BLI_thread_queue_nowait(ThreadQueue *queue)<br>
{<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_lock(&amp;queue-&gt;mutex);<br>
<br>
&nbsp;&nbsp;&nbsp; queue-&gt;nowait= 1;<br>
<br>
&nbsp;&nbsp;&nbsp; /* signal threads waiting to pop */<br>
&nbsp;&nbsp;&nbsp; pthread_cond_signal(&amp;queue-&gt;cond);<br>
&nbsp;&nbsp;&nbsp; pthread_mutex_unlock(&amp;queue-&gt;mutex);<br>
}<br>
<br>
<br>
กก</p>
<p>กก</p>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; <a href="PocketRuler.htm">                  







                       <img src="picture/back.gif" style="border: medium none ;" alt="back.gif (341 bytes)" height="35" width="32"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm">
<img src="picture/up.gif" style="border: medium none ;" alt="up.gif (335 bytes)" height="32" width="35"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none ;" alt="next.gif (337 bytes)" height="35" width="32">          


</p>

</body></html>