
    xKg                     D   d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZmZmZ ddlmZmZmZmZmZmZ ddlZddlmZ ddlm Z  edz
  Z!	 ddl"m#Z#  e#        dd	l$m%Z% d
Z&	 ddl$m(Z( d
Z)	 ddl*Z+d
Z, ejZ                  e)d      Z. ejZ                  e&d      Z/e)xr e(j`                  dk(  Z1 ejZ                  e1d      Z2ejf                  ji                  d      Z5ejf                  ji                  d      Z6ejn                  dk  Z8e8Z9e5 Z:d Z;e,rd Z<nd Z<d Z=d Z> G d de?      Z@ G d de@      ZA G d de?      ZB G d d e@      ZC G d! d"e@      ZD G d# d$e@      ZEd% ZFd& ZGe
j                  ZI G d' d(e?      ZJd) ZK eGeIej                        ZM eG eKd*       ZNe5s eG eKd+       ZO eG eKd,       ZP eG eKd-       ZQ G d. d/e      ZRe j                  d0v ZT ejZ                  eTd1       G d2 d3eR             ZUeUj                           G d4 d5e?      ZW G d6 d7eWeR      ZXeXj                           G d8 d9e      ZYe G d: d;eY             ZZeZj                          e G d< d=eY             Z[e G d> d?eY             Z\ee2 G d@ dAeY                    Z]ee/ G dB dCeY                    Z^e G dD dEe             Z_ee. G dF dGe                    Z`eadHk(  r ej                          yy# e'$ r dZ&Y w xY w# e'$ r dZ)Y w xY w# e'$ r dZ,Y w xY w)Iz
Tests the parallel backend
    N)jit	vectorizeguvectorizeset_num_threads)temp_directoryoverride_configTestCasetagskip_parfors_unsupported
linux_only)_TIMEOUT)configg      N@)_check_tbb_version_compatible)tbbpoolTF)omppoolzOpenMP threadpool requiredzTBB threadpool requiredGNUzGNU OpenMP only testswindarwinl        c                 2    t        j                  |       |z   S N)nponesnvs     e/home/alanp/www/video.onchill/myenv/lib/python3.12/site-packages/numba/tests/test_parallel_backend.pyfoor   H   s    771:>    c                     t        j                  t        j                  | | f      t        j                  | | f            }|t        j                  |       z   |z   S r   )r   dotr   arange)r   r   xs      r   linalgr#   M   sB    FF277Aq6?BGGQFO4299Q<!##r   c                 2    t        j                  |       |z   S r   )r   r!   r   s     r   r#   r#   Q   s    yy|ar   c                     | |z   S r    )abs     r   	ufunc_foor)   V   s    q5Lr   c                     | |z   |d<   y )Nr   r&   )r'   r(   outs      r   
gufunc_foor,   Z   s    UCFr   c                       e Zd Zd Zy)runnablec                     || _         y r   )_options)selfoptionss     r   __init__zrunnable.__init___   s	    r   N)__name__
__module____qualname__r3   r&   r   r   r.   r.   ^   s     r   r.   c                       e Zd Zd Zy)
jit_runnerc                      t        di | j                  t              }d}d}t        ||      } |||      }t        j                  j                  ||       y N   
   r&   )r   r0   r   r   testingassert_allcloser1   cfuncr'   r(   expectedgots         r   __call__zjit_runner.__call__e   sN    $$dmm$S)q!9Aqk


""8S1r   Nr4   r5   r6   rC   r&   r   r   r8   r8   c       2r   r8   c                       e Zd Zd Zd Zy)mask_runnerc                      || _         || _        y r   )runnermask)r1   rI   rJ   r2   s       r   r3   zmask_runner.__init__o   s    	r   c                 f    | j                   rt        | j                          | j                          y r   )rJ   r   rI   )r1   s    r   rC   zmask_runner.__call__s   s     99 DII&r   Nr4   r5   r6   r3   rC   r&   r   r   rG   rG   n   s    r   rG   c                       e Zd Zd Zy)linalg_runnerc                      t        di | j                  t              }d}d}t        ||      } |||      }t        j                  j                  ||       y r:   )r   r0   r#   r   r=   r>   r?   s         r   rC   zlinalg_runner.__call__}   sN    $$dmm$V,!Q<Aqk


""8S1r   NrD   r&   r   r   rN   rN   {   rE   r   rN   c                       e Zd Zd Zy)vectorize_runnerc                 ,    t        dgfi | j                  t              }t        j                  j	                  d      j                  t        j                        x}}t        ||      } |||      }t        j                  j                  ||       y )Nz(f4, f4)r<   )	r   r0   r)   r   randomastypefloat32r=   r>   r?   s         r   rC   zvectorize_runner.__call__   sp    8	:,8$--8C		  $++BJJ77AQ?Aqk


""8S1r   NrD   r&   r   r   rQ   rQ      s    2r   rQ   c                       e Zd Zd Zy)guvectorize_runnerc                 2   dg} t        |dfi | j                  t              }t        j                  j	                  d      j                  t        j                        x}}t        ||      } |||      }t        j                  j                  ||       y )Nz(f4, f4, f4[:])z	(),()->()r<   )
r   r0   r,   r   rS   rT   rU   r)   r=   r>   )r1   sigr@   r'   r(   rA   rB   s          r   rC   zguvectorize_runner.__call__   sx     !>C>>zJ		  $++BJJ77AQ?Aqk


""8S1r   NrD   r&   r   r   rW   rW      rE   r   rW   c                     |j                  d      }	 t        j                          t        t	        t        |       dz              D ]  }t        j                  |       } |          y # t        $ r}|j                  |       Y d }~y d }~ww xY w)Nqueueg      ?)
getfaulthandlerenablerangeintlenrS   choice	Exceptionput)fnlistkwargsq_fnes         r   chooserrk      sp    

7As3v;,-.Av&BD /  	as   AA) )	B2BBc                       fd}|S )Nc                     
       }d|i}t        d      D cg c]  } 	t        | f|       }}|D ]  }|j                           |D ]  }|j                           |j	                         syg }|j	                         s1|j                  |j                  d             |j	                         s1d}t        |dj                  |D cg c]  }t        |       c}      z        y c c}w c c}w )Nr[   r;   )targetargsrf   Fz)Error(s) occurred in delegated runner:
%s
)	r_   rk   startjoinemptyappendr\   RuntimeErrorrepr)re   rg   kwsithstherrors_msgr"   parallel_class
queue_impls            r   run_compilez$compile_factory.<locals>.run_compile   s    Lla" 1 WF9SI  	 "BHHJ BGGI wwyFggiaeeEl+ ggi?Dtdii&0I&Qa&0I&JJKK " 1Js   C+C0r&   )r}   r~   r   s   `` r   compile_factoryr      s    L r   c                       e Zd Zd Zd Zy)_proc_class_implc                     || _         y r   )_method)r1   methods     r   r3   z_proc_class_impl.__init__   s	    r   c                 d    t        j                  | j                        } |j                  |i |S r   )multiprocessingget_contextr   Process)r1   ro   rf   ctxs       r   rC   z_proc_class_impl.__call__   s,    ))$,,7s{{D+F++r   NrL   r&   r   r   r   r      s    ,r   r   c                 p    | dk(  rd } t        j                  |       }t        |       }|j                  }||fS )Ndefault)r   r   r   Queue)r   r   procr[   s       r   _get_mp_classesr      s<    

%
%f
-CF#DIIE;r   spawnfork
forkserverr   c                      e Zd ZdZ ed       edd       edd       ed       edd       ed       edd       eddd       ed       edd       eddd      gZe	s9 edd	       eddd
       edd	       eddd
      gZ
ej                  e
       ej                  dk  rg ZnddgZg ZeD ]!  ZeD ]  Zej%                   eee              # ddgZej%                  d       er"ej%                  d       ej%                  d        ede	 	      g edd      g edd      geedZddhZddZy)TestParallelBackendBasez6
    Base class for testing the parallel backends
    T)nopython)r   cache)r   nogilparallel)r   rn   )r   rn   r   )r   r   )r   r   r         	threadingrS   multiprocessing_spawnmultiprocessing_forkmultiprocessing_forkserver)concurrent_jitconcurrent_vectorizeconcurrent_guvectorizeconcurrent_mix_useconcurrent_mix_use_masksomptbbc                 4   t        | j                  j                        | _        t	        d| j                        5  |dk(  rt        |       n|dk(  rt        |       n|dk(  rt        |       n|dk(  rt        |       n|dk(  rt        |       nt|dk(  rat
        t        g}t        r*|j                  t               |j                  t               t        j                  |       |D ]
  } ||        nt        d|z        d d d        y # 1 sw Y   y xY w)	N	CACHE_DIRr   r   r   r   multiprocessing_defaultrS   zUnknown parallelism supplied %s)r   	__class__r4   
_cache_dirr   thread_implfork_proc_implforkserver_proc_implspawn_proc_impldefault_proc_impl_HAVE_OS_FORKrt   rS   shuffle
ValueError)r1   re   parallelismpsimpls        r   r   z#TestParallelBackendBase.run_compile  s    ()@)@A[$//:k)F# 66v& <<$V, 77' 99!&)(!?3 IIn-II23r"DL  !5CE E+ ;::s   C
DDN)r   )r4   r5   r6   __doc__r8   rN   rQ   rW   	all_impls_parfors_unsupportedparfor_implsextendr   NUMBA_NUM_THREADSmasks
mask_implsr   rJ   rt   rG   r   r   runnerssafe_backendsr   r&   r   r   r   r      s   
 	D!D-D-t$t40$'$z:$zFD)D<D4HI  t4t4@4$74$dC	
 	&!#AJDk$56   )K./1278 4H0HJ
 d:>!
 Z@#
 ($.G ENMEr   r   )r   r   	workqueuezThreading layer not explicitc                        e Zd ZdZed        Zy)TestParallelBackendav   These are like the numba.tests.test_threadsafety tests but designed
    instead to torture the parallel backend.
    If a suitable backend is supplied via NUMBA_THREADING_LAYER these tests
    can be run directly. This test class cannot be run using the multiprocessing
    option to the test runner (i.e. `./runtests -m`) as daemon processes cannot
    have children.
    c                     | j                   D ]O  }| j                  j                         D ]0  \  }}d|z   dz   |z   }d } |||      }||_        t	        | ||       2 Q y )Ntest_rh   c                       fd}|S )Nc                     t        j                         }|j                  rd}| j                  |       y | j	                         y )Nz)daemonized processes cannot have children)r   )r   current_processdaemonskipTestr   )r1   selfprocr|   r   ps      r   test_methodzBTestParallelBackend.generate.<locals>.methgen.<locals>.test_methodJ  s<    #2#B#B#D#??#ND MM$/ ,,Tq,Ar   r&   )r   r   r   s   `` r   methgenz-TestParallelBackend.generate.<locals>.methgenI  s    B '&r   )r   r   itemsr4   setattr)clsr   namer   methnamer   ri   s          r   generatezTestParallelBackend.generateC  sd    A!kk//1
d"Q;,t3	' T1%&Xr* 2 !r   N)r4   r5   r6   r   classmethodr   r&   r   r   r   r   6  s     + +r   r   c                   F    e Zd Zee ej                  dd      dZd Zd Z	y)TestInSubprocessF r   r   r   c                    t        j                  |t         j                  t         j                  |      }t        j                  t
        |j                        }	 |j                          |j                         \  }}|j                  dk7  r*t        d|j                  d|j                         d      |j                         |j                         f|j                          S # |j                          w xY w)Nstdoutstderrenvr   process failed with code : stderr follows
rp   
subprocessPopenPIPEr   Timer_TEST_TIMEOUTkillrq   communicate
returncodeAssertionErrordecodecancelr1   cmdliner   popentimeoutr+   errs          r   run_cmdzTestInSubprocess.run_cmd`  s      (2(2%(*
 //-<		MMO((*HC1$$%%szz|56 6 ::<-NNGNNs   A;C' 'C9c                     t         j                  j                         }t        |      |d<   t        j
                  dd|g}| j                  ||      S )NNUMBA_THREADING_LAYERz-mznumba.runtests)osenvironcopystrsys
executabler   )r1   testthreading_layerenv_copyr   s        r   run_test_in_separate_processz-TestInSubprocess.run_test_in_separate_processs  sF    ::??$,/,@()>>4)94@||GX..r   N)
r4   r5   r6   skip_no_tbbskip_no_ompunittestskipIfbackendsr   r   r&   r   r   r   r   [  s)    "",X__UB79H&/r   r   c                   4    e Zd ZdZdZed        Zed        Zy)TestSpecificBackenda  
    This is quite contrived, for each test in the TestParallelBackend tests it
    generates a test that will run the TestParallelBackend test in a new python
    process with an environment modified to ensure a specific threadsafe backend
    is used. This is with view of testing the backends independently and in an
    isolated manner such that if they hang/crash/have issues, it doesn't kill
    the test suite.
    Fc           	         
 | j                   }t        j                  }d|z   dz   |z   }|d|d|

fd}d|d|d}	t        | |	 t	        d       ||                   y )Nr   rh   .c                 L   | j                        \  }}| j                  rt        d|d|d       t        j                  d|      }| | j                  |j                  d             | j                  d|       | j                  d|v       | j                  d|v       y )	Nz
stdout:
 "z"
 stderr:
 ""z\.\.\. skipped '(.*?)'r   OKFAILERROR)	r   _DEBUGprintresearchr   groupassertIn
assertTrue)r1   orj   mbackendinjected_methods       r   test_templatez2TestSpecificBackend._inject.<locals>.test_template  s    44_gNDAq{{1a@A 		3Q7A}aggaj)MM$"OOF!O,OOG1,-r   long_running)r5   r   r4   r   r
   )r   r   r   r  backend_guardthemodtheclsr   r  injected_testr  s      `      @r   _injectzTestSpecificBackend._inject  sj    $--Q;$t+(.A	. ,-dG<]#N#M-$@A	Cr   c           	      6   | j                   j                         D ]|  \  }}| j                  D ]h  }| j                  j	                         D ]I  }|dv r%|dk(  r t
        j                  j                  d      r,|dv r|dk(  r6| j                  ||||       K j ~ y )N)r   rS   r   linux)r   rS   r   )	r  r   r   r   keysr   platform
startswithr  )r   r  r  r   r   s        r   r   zTestSpecificBackend.generate  s    &)ll&8&8&:"G]__KK,,.D ??5(LL33G<  44#{2 KK4-@ / % ';r   N)r4   r5   r6   r   r  r   r  r   r&   r   r   r  r  z  s8     FC C. A Ar   r  c                   b    e Zd ZdZdej
                  j                  e      z  Zddeiz  Z	ddZ
y)ThreadLayerTestHelperzP
    Helper class for running an isolated piece of code based on a template
    z%ra  if 1:
    import sys
    sys.path.insert(0, "%(here)r")
    import multiprocessing
    import numpy as np
    from numba import njit
    import numba
    try:
        import threading_backend_usecases
    except ImportError as e:
        print("DEBUG:", sys.path)
        raise e
    import os

    sigterm_handler = threading_backend_usecases.sigterm_handler
    busy_func = threading_backend_usecases.busy_func

    def the_test():
        %%s

    if __name__ == "__main__":
        the_test()
    hereNc                 V   |,t         j                  j                         }t        d      |d<   t	        j
                  |t        j                  t        j                  |      }t        j                  t        |j                        }	 |j                          |j                         \  }}|j                  dk7  r*t        d|j                  d|j                         d      	 |j!                          |j                         |j                         fS # |j!                          w xY w)Nr   r   r   r   r   r   rp   )r   r   r   r   r   r   r   r   r   r   r   rq   r   r   r   r   r   r   s          r   r   zThreadLayerTestHelper.run_cmd  s    ;**//#C+.u:C'(  (2(2%(*
 //-<	MMO((*HC1$$%%szz|56 6 %
 NNzz|SZZ\)) NNs   	AD D(r   )r4   r5   r6   r   r   pathdirname__file___heretemplater   r&   r   r   r$  r$    s:    
 277??8,,E, 5/-H0*r   r$  c                   b    e Zd ZdZdZee ej                  dd      dZ	e
d        Ze
d        Zy)TestThreadingLayerSelectionz@
    Checks that numba.threading_layer() reports correctly.
    Fr   r   c           	      ^    fd}dz  }t        | | t        d       ||                   y )Nc                 
   d}| j                   |z  z  }t        j                  d|g}t        j                  j                         }t              |d<   | j                  ||      \  }}| j                  rt        ||       y y )Nzif 1:
                X = np.arange(1000000.)
                Y = np.arange(1000000.)
                Z = busy_func(X, Y)
                assert numba.threading_layer() == '%s'
            -cr   r   )
r+  r   r   r   r   r   r   r   r  r  )r1   bodyrunmer   r   r+   r   r  s          r   r  z:TestThreadingLayerSelection._inject.<locals>.test_template  sx    D MMTG^4E~~tU3G**//#C+.w<C'(||G|5HC{{c3 r   z test_threading_layer_selector_%s	important)r   r
   )r   r  r  r  r  s    `   r   r  z#TestThreadingLayerSelection._inject  s5    	  ;WD] K }!=>	@r   c                 l    | j                   j                         D ]  \  }}| j                  ||        y r   )r  r   r  )r   r  r  s      r   r   z$TestThreadingLayerSelection.generate  s,    &)ll&8&8&:"G]KK/ ';r   N)r4   r5   r6   r   r  r   r   r   r  r  r   r  r   r&   r   r   r-  r-    sU     F"",X__UB79H @ @( 0 0r   r-  c                   r    e Zd ZdefdZeed               Zeed               Zed        Z	ed        Z
d Zy)	TestThreadingLayerPriorityenv_varc                     t         j                  j                         }d|d<   ||d<   d| d}t        j                  dt        j                  |      g}| j                  ||       y)	zJTest setting priority via env var NUMBA_THREADING_LAYER_PRIORITY.
        r   r   NUMBA_THREADING_LAYER_PRIORITYa  
                import numba

                # trigger threading layer decision
                # hence catching invalid THREADING_LAYER_PRIORITY
                @numba.jit(
                    'float64[::1](float64[::1], float64[::1])',
                    nopython=True,
                    parallel=True,
                )
                def plus(x, y):
                    return x + y

                captured_envvar = list("a	  ".split())
                assert numba.config.THREADING_LAYER_PRIORITY ==                     captured_envvar, "priority mismatch"
                assert numba.threading_layer() == captured_envvar[0],                    "selected backend mismatch"
                r0  r1  N)r   r   r   r   r   textwrapdedentr   )r1   r8  r   codecmds        r   each_env_varz'TestThreadingLayerPriority.each_env_var  ss     jjoo'0#$07,-) *1	 2( NNOOD!

 	Sc"r   c                     g d}t        j                  |      D ]$  }dj                  |      }| j                  |       & y )Nr    )	itertoolspermutationsrr   r?  )r1   r   r   r8  s       r   test_valid_env_varz-TestThreadingLayerPriority.test_valid_env_var8  s9     .''0AhhqkGg& 1r   c                     d}| j                  t              5 }| j                  |       d d d        dD ](  }| j                  | t	        j
                               * y # 1 sw Y   7xY w)Nztbb omp workqueue notvalidhere)z!THREADING_LAYER_PRIORITY invalid:zIt must be a permutation of)assertRaisesr   r?  r  r   	exception)r1   r8  raisesmsgs       r   test_invalid_env_varz/TestThreadingLayerPriority.test_invalid_env_var@  s^     3~.&g& /
C MMSEC(8(8$9:	
 /.s   A  A)c                 4    dD ]  }| j                  |        y )N)zomp tbb workqueuezomp workqueue tbbr?  r1   r8  s     r   test_ompz#TestThreadingLayerPriority.test_ompL      AGg& Br   c                 4    dD ]  }| j                  |        y )N)ztbb omp workqueueztbb workqueue omprL  rM  s     r   test_tbbz#TestThreadingLayerPriority.test_tbbQ  rO  r   c                 4    dD ]  }| j                  |        y )N)zworkqueue tbb ompzworkqueue omp tbbrL  rM  s     r   test_workqueuez)TestThreadingLayerPriority.test_workqueueV  s    AGg& Br   N)r4   r5   r6   r   r?  r   r   rD  rJ  rN  rQ  rS  r&   r   r   r7  r7    st    #C #B '  ' ;  ; ' ' ' ''r   r7  c                   l    e Zd ZdZdZed        Zed        Zd Z	 e
j                  ed      d        Zy)	TestMiscBackendIssueszL
    Checks fixes for the issues with threading backends implementation
    Fc                     d}t         j                  d|g}t        j                  j	                         }d|d<   d|d<   | j                  ||       y)	z8
        Tests that OMP does not overflow stack
        a  if 1:
            from numba import vectorize, threading_layer
            import numpy as np

            @vectorize(['f4(f4,f4,f4,f4,f4,f4,f4,f4)'], target='parallel')
            def foo(a, b, c, d, e, f, g, h):
                return a+b+c+d+e+f+g+h

            x = np.ones(2**20, np.float32)
            foo(*([x]*8))
            assert threading_layer() == "omp", "omp not found"
        r0  r   r   100KOMP_STACKSIZEr1  Nr   r   r   r   r   r   r1   r3  r   r   s       r   test_omp_stack_overflowz-TestMiscBackendIssues.test_omp_stack_overflowb  sP    
 >>4/jjoo',#$%OW#&r   c                     d}t         j                  d|g}t        j                  j	                         }d|d<   d|d<   | j                  ||       y)	zq
        Tests that TBB works well with single thread
        https://github.com/numba/numba/issues/3440
        aM  if 1:
            from numba import njit, prange, threading_layer

            @njit(parallel=True)
            def foo(n):
                acc = 0
                for i in prange(n):
                    acc += i
                return acc

            foo(100)
            assert threading_layer() == "tbb", "tbb not found"
        r0  r   r   1r   r1  NrY  rZ  s       r   test_single_thread_tbbz,TestMiscBackendIssues.test_single_thread_tbby  sQ     >>4/jjoo',#$#& W#&r   c                 j   d}t         j                  d|g}t        j                  j	                         }d|d<   d|d<   	 | j                  ||      \  }}y
# t        $ rS}| j                  rt               t        |      }| j                  d|       d	}| j                  ||       Y d
}~y
d
}~ww xY w)zW
        Tests workqueue raises sigabrt if a nested parallel call is performed
        a  if 1:
            from numba import njit, prange
            import numpy as np

            @njit(parallel=True)
            def nested(x):
                for i in prange(len(x)):
                    x[i] += 1


            @njit(parallel=True)
            def main():
                Z = np.zeros((5, 10))
                for i in prange(Z.shape[0]):
                    nested(Z[i])
                return Z

            main()
        r0  r   r   4r   r1  zfailed with codezTNumba workqueue threading layer is terminating: Concurrent access has been detected.N)r   r   r   r   r   r   r   r  r  r   r  )	r1   r3  r   r   r+   r   rj   e_msgrA   s	            r   +test_workqueue_aborts_on_nested_parallelismzATestMiscBackendIssues.test_workqueue_aborts_on_nested_parallelism  s    & >>4/jjoo'2#$#& 	+||G|5HC 		+{{c3FEMM,e4?HMM(E**		+s   A 	B2A	B--B2zTest needs fork(2)c                     d}t         j                  d|g}t        j                  j	                         }d|d<   d|d<   | j                  ||       y )Na  if 1:
            from numba import njit, prange, threading_layer
            import numpy as np
            import multiprocessing

            if __name__ == "__main__":
                # Need for force fork context (OSX default is "spawn")
                multiprocessing.set_start_method('fork')

                @njit(parallel=True)
                def func(x):
                    return 10. * x

                arr = np.arange(2.)

                # run in single process to start Numba's thread pool
                np.testing.assert_allclose(func(arr), func.py_func(arr))

                # now run in a multiprocessing pool to get a fork from a
                # non-main thread
                with multiprocessing.Pool(10) as p:
                    result = p.map(func, [arr])
                np.testing.assert_allclose(result,
                                           func.py_func(np.expand_dims(arr, 0)))

                assert threading_layer() == "workqueue"
        r0  r   r   r`  r   r1  rY  rZ  s       r   0test_workqueue_handles_fork_from_non_main_threadzFTestMiscBackendIssues.test_workqueue_handles_fork_from_non_main_thread  sQ    6 >>4/jjoo'2#$#& W#&r   N)r4   r5   r6   r   r  r   r[  r   r^  rb  r   
skipUnlessr   rd  r&   r   r   rU  rU  [  s^     F' ', ' '0'+R X(<=&' >&'r   rU  c                   R    e Zd ZdZdZd Zd Zd Zed        Z	d Z
d Zed	        Zy
)TestForkSafetyIssueszV
    Checks Numba's behaviour in various situations involving GNU OpenMP and fork
    Fc                 V    d}t         j                  d|g}| j                  |      \  }}y )Nzsif 1:
            from numba.np.ufunc import omppool
            assert omppool.openmp_vendor == 'GNU'
            r0  )r   r   r   )r1   r3  r   r+   r   s        r   !test_check_threading_layer_is_gnuz6TestForkSafetyIssues.test_check_threading_layer_is_gnu  s-     >>4/<<(Sr   c                     d}| j                   |z  }t        j                  d|g}	 | j                  |      \  }}y# t        $ r%}| j                  dt        |             Y d}~yd}~ww xY w)z~
        Whilst normally valid, this actually isn't for Numba invariant of OpenMP
        Checks SIGABRT is received.
        zif 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            Z = busy_func(X, Y)
            pid = os.fork()
            if pid  == 0:
                Z = busy_func(X, Y)
            else:
                os.wait()
        r0  zfailed with code -6N)r+  r   r   r   r   r  r   )r1   r2  r3  r   r+   r   rj   s          r   !test_par_parent_os_fork_par_childz6TestForkSafetyIssues.test_par_parent_os_fork_par_child  sf    
	 $>>4/	9||G,HC 	9MM/Q88	9s   ; 	A)A$$A)c                     d}| j                   |z  }t        j                  d|g}| j                  |      \  }}| j                  rt        ||       yy)au  
        Implicit use of multiprocessing fork context.
        Does this:
        1. Start with OpenMP
        2. Fork to processes using OpenMP (this is invalid)
        3. Joins fork
        4. Check the exception pushed onto the queue that is a result of
           catching SIGTERM coming from the C++ aborting on illegal fork
           pattern for GNU OpenMP
        a  if 1:
            mp = multiprocessing.get_context('fork')
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            q = mp.Queue()

            # Start OpenMP runtime on parent via parallel function
            Z = busy_func(X, Y, q)

            # fork() underneath with no exec, will abort
            proc = mp.Process(target = busy_func, args=(X, Y, q))
            proc.start()

            err = q.get()
            assert "Caught SIGTERM" in str(err)
        r0  Nr+  r   r   r   r  r  r1   r2  r3  r   r+   r   s         r   *test_par_parent_implicit_mp_fork_par_childz?TestForkSafetyIssues.test_par_parent_implicit_mp_fork_par_child  sP      $>>4/<<(S;;#sO r   c                     d}| j                   |z  }t        j                  d|g}| j                  |      \  }}| j                  rt        ||       yy)au  
        Explicit use of multiprocessing fork context.
        Does this:
        1. Start with OpenMP
        2. Fork to processes using OpenMP (this is invalid)
        3. Joins fork
        4. Check the exception pushed onto the queue that is a result of
           catching SIGTERM coming from the C++ aborting on illegal fork
           pattern for GNU OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('fork')
            q = ctx.Queue()

            # Start OpenMP runtime on parent via parallel function
            Z = busy_func(X, Y, q)

            # fork() underneath with no exec, will abort
            proc = ctx.Process(target = busy_func, args=(X, Y, q))
            proc.start()
            proc.join()

            err = q.get()
            assert "Caught SIGTERM" in str(err)
        r0  Nrm  rn  s         r   *test_par_parent_explicit_mp_fork_par_childz?TestForkSafetyIssues.test_par_parent_explicit_mp_fork_par_child-  sP    " $>>4/<<(S;;#sO r   c                     d}| j                   |z  }t        j                  d|g}| j                  |      \  }}| j                  rt        ||       yy)z
        Explicit use of multiprocessing spawn, this is safe.
        Does this:
        1. Start with OpenMP
        2. Spawn to processes using OpenMP
        3. Join spawns
        4. Run some more OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('spawn')
            q = ctx.Queue()

            # Start OpenMP runtime and run on parent via parallel function
            Z = busy_func(X, Y, q)
            procs = []
            for x in range(20): # start a lot to try and get overlap
                ## fork() + exec() to run some OpenMP on children
                proc = ctx.Process(target = busy_func, args=(X, Y, q))
                procs.append(proc)
                sys.stdout.flush()
                sys.stderr.flush()
                proc.start()

            [p.join() for p in procs]

            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")

            # Run some more OpenMP on parent
            Z = busy_func(X, Y, q)
        r0  Nrm  rn  s         r   -test_par_parent_mp_spawn_par_child_par_parentzBTestForkSafetyIssues.test_par_parent_mp_spawn_par_child_par_parentP  sP    : $>>4/<<(S;;#sO r   c                     d}| j                   |z  }t        j                  d|g}| j                  |      \  }}| j                  rt        ||       yy)a  
        Implicit use of multiprocessing (will be fork, but cannot declare that
        in Py2.7 as there's no process launch context).
        Does this:
        1. Start with no OpenMP
        2. Fork to processes using OpenMP
        3. Join forks
        4. Run some OpenMP
        a,  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            q = multiprocessing.Queue()

            # this is ok
            procs = []
            for x in range(10):
                # fork() underneath with but no OpenMP in parent, this is ok
                proc = multiprocessing.Process(target = busy_func,
                                               args=(X, Y, q))
                procs.append(proc)
                proc.start()

            [p.join() for p in procs]

            # and this is still ok as the OpenMP happened in forks
            Z = busy_func(X, Y, q)
            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")
        r0  Nrm  rn  s         r   =test_serial_parent_implicit_mp_fork_par_child_then_par_parentzRTestForkSafetyIssues.test_serial_parent_implicit_mp_fork_par_child_then_par_parent|  P    2 $>>4/<<(S;;#sO r   c                     d}| j                   |z  }t        j                  d|g}| j                  |      \  }}| j                  rt        ||       yy)z
        Explicit use of multiprocessing 'fork'.
        Does this:
        1. Start with no OpenMP
        2. Fork to processes using OpenMP
        3. Join forks
        4. Run some OpenMP
        a  if 1:
            X = np.arange(1000000.)
            Y = np.arange(1000000.)
            ctx = multiprocessing.get_context('fork')
            q = ctx.Queue()

            # this is ok
            procs = []
            for x in range(10):
                # fork() underneath with but no OpenMP in parent, this is ok
                proc = ctx.Process(target = busy_func, args=(X, Y, q))
                procs.append(proc)
                proc.start()

            [p.join() for p in procs]

            # and this is still ok as the OpenMP happened in forks
            Z = busy_func(X, Y, q)
            try:
                q.get(False)
            except multiprocessing.queues.Empty:
                pass
            else:
                raise RuntimeError("Queue was not empty")
        r0  Nrm  rn  s         r   =test_serial_parent_explicit_mp_fork_par_child_then_par_parentzRTestForkSafetyIssues.test_serial_parent_explicit_mp_fork_par_child_then_par_parent  rv  r   N)r4   r5   r6   r   r  ri  rk  ro  r   rq  rs  ru  rx  r&   r   r   rg  rg    sS     F)9,B    D*X'R & &r   rg  c                   0    e Zd ZdZed        Zed        Zy)TestTBBSpecificIssuesFc                     d}t         j                  d|g}| j                  |      \  }}d}| j                  ||       | j                  rt        d|       t        d|       y y )Na%  if 1:
            import threading
            import numba
            numba.config.THREADING_LAYER='tbb'
            from numba import njit, prange, objmode
            from numba.core.serialize import PickleCallableByPath
            import os

            e_running = threading.Event()
            e_proceed = threading.Event()

            def indirect_core():
                e_running.set()
                # wait for forker() to have forked
                while not e_proceed.isSet():
                    pass

            indirect = PickleCallableByPath(indirect_core)

            @njit
            def obj_mode_func():
                with objmode():
                    indirect()

            @njit(parallel=True, nogil=True)
            def work():
                acc = 0
                for x in prange(10):
                    acc += x
                obj_mode_func()
                return acc

            def runner():
                work()

            def forker():
                # wait for the jit function to say it's running
                while not e_running.isSet():
                    pass
                # then fork
                os.fork()
                # now fork is done signal the runner to proceed to exit
                e_proceed.set()

            numba_runner = threading.Thread(target=runner,)
            fork_runner =  threading.Thread(target=forker,)

            threads = (numba_runner, fork_runner)
            for t in threads:
                t.start()
            for t in threads:
                t.join()
        r0  z9Attempted to fork from a non-main thread, the TBB libraryOUT:ERR:)r   r   r   r  r  r  )r1   r3  r   r+   r   msg_heads         r   test_fork_from_non_main_threadz4TestTBBSpecificIssues.test_fork_from_non_main_thread  sa    64l >>4/<<(SNh$;;&#&# r   c                 ~   | j                          d}dj                  d|      }t        j                  d|g}t        j
                  j                         }d|d<   | j                  ||      \  }}||v r| j                  d       n| j                  d	|       | j                  rt        d
|       t        d|       y y )NzSKIP: COMPILATION FAILEDax  if 1:
            import ctypes
            import sys
            import multiprocessing as mp
            from tempfile import TemporaryDirectory, NamedTemporaryFile
            from numba.pycc.platform import Toolchain, external_compiler_works
            from numba import njit, prange, threading_layer
            import faulthandler
            faulthandler.enable()
            if not external_compiler_works():
                raise AssertionError('External compilers are not found.')
            with TemporaryDirectory() as tmpdir:
                with NamedTemporaryFile(dir=tmpdir) as tmpfile:
                    try:
                        src = """
                        #define TBB_PREVIEW_WAITING_FOR_WORKERS 1
                        #include <tbb/tbb.h>
                        static tbb::task_scheduler_handle tsh;
                        extern "C"
                        {
                        void launch(void)
                        {
                            tsh = tbb::task_scheduler_handle::get();
                        }
                        }
                        """
                        cxxfile = f"{tmpfile.name}.cxx"
                        with open(cxxfile, 'wt') as f:
                            f.write(src)
                        tc = Toolchain()
                        object_files = tc.compile_objects([cxxfile,],
                                                           output_dir=tmpdir)
                        dso_name = f"{tmpfile.name}.so"
                        tc.link_shared(dso_name, object_files,
                                       libraries=['tbb',],
                                       export_symbols=['launch'])
                        # Load into the process, it doesn't matter whether the
                        # DSO exists on disk once it's loaded in.
                        DLL = ctypes.CDLL(dso_name)
                    except Exception as e:
                        # Something is broken in compilation, could be one of
                        # many things including, but not limited to: missing tbb
                        # headers, incorrect permissions, compilers that don't
                        # work for the above
                        print(e)
                        print('BROKEN_COMPILERS')
                        sys.exit(0)

                    # Do the test, launch this library and also execute a
                    # function with the TBB threading layer.

                    DLL.launch()

                    @njit(parallel=True)
                    def foo(n):
                        acc = 0
                        for i in prange(n):
                            acc += i
                        return acc

                    foo(1)

            # Check the threading layer used was TBB
            assert threading_layer() == 'tbb'

            # Use mp context for a controlled version of fork, this triggers the
            # reported bug.

            ctx = mp.get_context('fork')
            def nowork():
                pass
            p = ctx.Process(target=nowork)
            p.start()
            p.join(10)
            print("SUCCESS")
            BROKEN_COMPILERSr0  r   r   r1  z3Compilation of DSO failed. Check output for detailsSUCCESSr|  r}  )skip_if_no_external_compilerreplacer   r   r   r   r   r   r   r  r  r  )r1   r  r3  r   r   r+   r   s          r   &test_lifetime_of_task_scheduler_handlez<TestTBBSpecificIssues.test_lifetime_of_task_scheduler_handle0  s     	))+ 6KV *,<=W 	Z >>4/jjoo',#$<<S<1Ss"MMOPMM)S);;&#&# r   N)r4   r5   r6   r  r   r  r  r&   r   r   rz  rz    s4     FX Xt _ _r   rz  c                   ,    e Zd ZdZd Zed        Zd Zy)TestInitSafetyIssuesFc                    t        j                  |t         j                  t         j                        }t        j                  t
        |j                        }	 |j                          |j                         \  }}|j                  dk7  r*t        d|j                  d|j                         d      	 |j                          |j                         |j                         fS # |j                          w xY w)N)r   r   r   r   r   rp   r   )r1   r   r   r   r+   r   s         r   r   zTestInitSafetyIssues.run_cmd  s      (2(2: //-<	MMO((*HC1$$%%szz|56 6 %
 NNzz|SZZ\)) NNs   AC' 'C9c                 @   t         j                  j                  t         j                  j                  t              d      }t
        j                  |g}| j                  |      \  }}| j                  d|       | j                  rt        d|       t        d|       y y )Nzorphaned_semaphore_usecase.pyzleaked semaphorer|  r}  )r   r'  rr   r(  r)  r   r   r   assertNotInr  r  )r1   	test_filer   r+   r   s        r   test_orphaned_semaphorez,TestInitSafetyIssues.test_orphaned_semaphore  s|    
 GGLL!:!@B	>>9-<<(S 	+S1;;&#&# r   c                 8   dD ]  }	 t        j                  |       d}t        j                  d|j                  |      g}| j                  |      \  }}| j                  rt        d|       t        d|       | j                  ||        y # t        $ r Y w xY w)N)r   r   r   zimport numba; import multiprocessing;multiprocessing.set_start_method('{}');print(multiprocessing.get_context().get_start_method())r0  r|  r}  )
r   r   r   r   r   formatr   r  r  r  )r1   methr>  r   r+   r   s         r   test_lazy_lock_initz(TestInitSafetyIssues.test_lazy_lock_init  s     4D++D1MC ~~tSZZ-=>G||G,HC{{fc"fc"MM$$ 4
  s   B	BBN)r4   r5   r6   r  r   r   r  r  r&   r   r   r  r    s'     F*"   %r   r  c                       e Zd Zd Zy)TestOpenMPVendorsc                     t               }d|d<   d|d<   d|d<   |j                         D ]E  }t        j                  j	                  |      s#| j                  ||   t        j                         G y)z>
        Checks the OpenMP vendor strings are correct
        MSwin32Intelr   r   r  N)dictr   r   r!  r"  assertEqualr   openmp_vendor)r1   rA   ks      r   test_vendorszTestOpenMPVendors.test_vendors  sg     6 $! A||&&q)  !g.C.CD !r   N)r4   r5   r6   r  r&   r   r   r  r    s    Er   r  __main__)cr   r]   rB  r   r   rS   r  r   r   r;  r   r   numpyr   numbar   r   r   r   numba.tests.supportr   r   r	   r
   r   r   r[   t_queuenumba.testing.mainr   _RUNNER_TIMEOUT
numba.corer   r   numba.np.ufunc.parallelr   numba.np.ufuncr   _HAVE_TBB_POOLImportErrorr   _HAVE_OMP_POOLscipy.linalg.cython_lapackscipy_HAVE_LAPACKre  r   r   r  _gnuompskip_unless_gnu_ompr!  r"  _windows_osxmaxsize_32bitr   r   r   r#   r)   r,   objectr.   r8   rG   rN   rQ   rW   rk   r   Thread_thread_classr   r   r   r   r   r   r   r   r   THREADING_LAYER_specific_backendsr   r   r   r  r$  r-  r7  rU  rg  rz  r  r  r4   mainr&   r   r   <module>r     s      	  	  
     > >G G  :   #%
E!#&N&N%L
 "h!!.2NO!h!!.2KL

;W22e;)h))'3JK <<""5)
||x(		 
 $ 
 v  
2 2
& 
2H 22x 22 2(   ,v , mW]];!?7#;<$of&=>N*OL,IJ $_Y%?@ UEh UEp ++/JJ  ')GH+1 + I+B    /v />5A*,C 5Ap    3*H 3*l "0"7 "0 "0J  $ $ & C'!6 C' C'L F'1 F' F'T d0 d  dN 1   D 9%8 9% 9%x E E  E$ zHMMO y%  N  N  Ls6   %K8 ;L L 8LLLLLL