
    sh                     t   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKJrJrJrJr  SSKJrJrJrJrJrJr  SSKrSSKJr  SSKJ r   \S-
  r! SSK"J#r#  \#" 5         SS	K$J%r%  S
r& SSK$J(r(  S
r) SSK*r+S
r,\RZ                  " \)S5      r.\RZ                  " \&S5      r/\)=(       a    \(R`                  S:H  r1\RZ                  " \1S5      r2\Rf                  Ri                  S5      r5\Rf                  Ri                  S5      r6\Rn                  S:*  r8\8r9\5(       + r:S r;\,(       a  S r<OS r<S r=S r> " S S\?5      r@ " S S\@5      rA " S S\?5      rB " S S \@5      rC " S! S"\@5      rD " S# S$\@5      rES% rFS& rG\
R                  rI " S' S(\?5      rJS) rK\G" \I\R                  5      rM\G" \K" S*5      6 rN\5(       d  \G" \K" S+5      6 rO\G" \K" S,5      6 rP\G" \K" S-5      6 rQ " S. S/\5      rR\ R                  S0;   rT\RZ                  " \TS15       " S2 S3\R5      5       rU\UR                  5          " S4 S5\?5      rW " S6 S7\W\R5      rX\XR                  5          " S8 S9\5      rY\ " S: S;\Y5      5       rZ\ZR                  5         \ " S< S=\Y5      5       r[\ " S> S?\Y5      5       r\\\2 " S@ SA\Y5      5       5       r]\\/ " SB SC\Y5      5       5       r^\ " SD SE\5      5       r_\\. " SF SG\5      5       5       r`\aSH:X  a  \R                  " 5         gg! \' a    Sr& GNf = f! \' a    Sr) GNf = f! \' a    Sr, GNf = f)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                 4    [         R                  " U 5      U-   $ N)nponesnvs     u/Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/numba/tests/test_parallel_backend.pyfoor   H   s    771:>    c                     [         R                  " [         R                  " X 45      [         R                  " X 45      5      nU[         R                  " U 5      -   U-   $ r   )r   dotr   arange)r   r   xs      r   linalgr#   M   s>    FF277A6?BGGQFO4299Q<!##r   c                 4    [         R                  " U 5      U-   $ r   )r   r!   r   s     r   r#   r#   Q   s    yy|ar   c                 
    X-   $ r    )abs     r   	ufunc_foor)   V   s	    5Lr   c                     X-   US'   g )Nr   r&   )r'   r(   outs      r   
gufunc_foor,   Z   s    UCFr   c                       \ rS rSrS rSrg)runnable^   c                     Xl         g r   _options)selfoptionss     r   __init__runnable.__init___   s    r   r1   N)__name__
__module____qualname____firstlineno__r5   __static_attributes__r&   r   r   r.   r.   ^   s     r   r.   c                       \ rS rSrS rSrg)
jit_runnerc   c                     [        S0 U R                  D6" [        5      nSnSn[        X#5      nU" X#5      n[        R                  R                  XE5        g N   
   r&   )r   r2   r   r   testingassert_allcloser3   cfuncr'   r(   expectedgots         r   __call__jit_runner.__call__e   sF    $dmm$S)q9Ak


""81r   r&   Nr7   r8   r9   r:   rI   r;   r&   r   r   r=   r=   c       2r   r=   c                        \ rS rSrS rS rSrg)mask_runnern   c                     Xl         X l        g r   )runnermask)r3   rQ   rR   r4   s       r   r5   mask_runner.__init__o   s    	r   c                 p    U R                   (       a  [        U R                   5        U R                  5         g r   )rR   r   rQ   )r3   s    r   rI   mask_runner.__call__s   s     99 DII&r   )rR   rQ   Nr7   r8   r9   r:   r5   rI   r;   r&   r   r   rN   rN   n   s    r   rN   c                       \ rS rSrS rSrg)linalg_runner{   c                     [        S0 U R                  D6" [        5      nSnSn[        X#5      nU" X#5      n[        R                  R                  XE5        g r@   )r   r2   r#   r   rC   rD   rE   s         r   rI   linalg_runner.__call__}   sF    $dmm$V,!<Ak


""81r   r&   NrK   r&   r   r   rX   rX   {   rL   r   rX   c                       \ rS rSrS rSrg)vectorize_runner   c                 $   [        S/40 U R                  D6" [        5      n[        R                  R	                  S5      R                  [        R                  5      =p#[        X#5      nU" X#5      n[        R                  R                  XE5        g )Nz(f4, f4)rB   )	r   r2   r)   r   randomastypefloat32rC   rD   rE   s         r   rI   vectorize_runner.__call__   sf    :,8$--8C		  $++BJJ77Q?Ak


""81r   r&   NrK   r&   r   r   r]   r]      s    2r   r]   c                       \ rS rSrS rSrg)guvectorize_runner   c                 *   S/n[        US40 U R                  D6" [        5      n[        R                  R	                  S5      R                  [        R                  5      =p4[        X45      nU" X45      n[        R                  R                  XV5        g )Nz(f4, f4, f4[:])z	(),()->()rB   )
r   r2   r,   r   r`   ra   rb   r)   rC   rD   )r3   sigrF   r'   r(   rG   rH   s          r   rI   guvectorize_runner.__call__   sn     !C>>zJ		  $++BJJ77Q?Ak


""81r   r&   NrK   r&   r   r   re   re      rL   r   re   c                 *   UR                  S5      n [        R                  " 5         [        [	        [        U 5      S-  5      5       H   n[        R                  " U 5      nU" 5         M"     g ! [         a  nUR                  U5         S nAg S nAff = f)Nqueueg      ?)
getfaulthandlerenablerangeintlenr`   choice	Exceptionput)fnlistkwargsq_fnes         r   chooserr{      sp    

7As3v;,-.Av&BD /  	as   AA- -
B7BBc                    ^ ^ U U4S jnU$ )Nc                   > T
" 5       nSU0n[        S5       Vs/ s H  nT	" [        U 4US9PM     nnU H  nUR                  5         M     U H  nUR                  5         M     UR	                  5       (       d  / nUR	                  5       (       d7  UR                  UR                  S5      5        UR	                  5       (       d  M7  Sn[        USR                  U Vs/ s H  n[        U5      PM     sn5      -  5      eg s  snf s  snf )Nrk   rA   )targetargsrv   Fz)Error(s) occurred in delegated runner:
%s
)	ro   r{   startjoinemptyappendrl   RuntimeErrorrepr)ru   rw   kwsithstherrors_msgr"   parallel_class
queue_impls            r   run_compile$compile_factory.<locals>.run_compile   s    Lla" 1 WF9SI  	 "BHHJ BGGI wwyyFggiiaeeEl+ ggii?Dtdii&0I&Qa&0I&JJKK " 1Js   DDr&   )r   r   r   s   `` r   compile_factoryr      s    L r   c                        \ rS rSrS rS rSrg)_proc_class_impl   c                     Xl         g r   _method)r3   methods     r   r5   _proc_class_impl.__init__   s    r   c                 f    [         R                  " U R                  5      nUR                  " U0 UD6$ r   )multiprocessingget_contextr   Process)r3   r   rv   ctxs       r   rI   _proc_class_impl.__call__   s*    ))$,,7{{D+F++r   r   NrV   r&   r   r   r   r      s    ,r   r   c                 r    U S:X  a  S n [         R                  " U 5      n[        U 5      nUR                  nX#4$ )Ndefault)r   r   r   Queue)r   r   procrk   s       r   _get_mp_classesr      s:    

%
%f
-CF#DIIE;r   spawnfork
forkserverr   c                   V   \ rS rSrSr\" SS9\" SSS9\" SSS9\" SS9\" SSS9\" SS9\" SSS9\" SSSS	9\" SS9\" SSS9\" SSSS	9/r	\
(       d-  \" SSS
9\" SSSS9\" SSS
9\" SSSS9/r\	R                  \5        \R                  S:  a  / rOSS/r/ r\	 H$  r\ H  r\R'                  \" \\5      5        M     M&     SS/r\R'                  S5        \(       a"  \R'                  S5        \R'                  S5        \" S\
(       + S
9/\" SSS9/\" SSS9/\	\S.rSS1rSS jrSrg)TestParallelBackendBase   z.
Base class for testing the parallel backends
T)nopython)r   cache)r   nogilparallel)r   r~   )r   r~   r   )r   r   )r   r   r         	threadingr`   multiprocessing_spawnmultiprocessing_forkmultiprocessing_forkserver)concurrent_jitconcurrent_vectorizeconcurrent_guvectorizeconcurrent_mix_useconcurrent_mix_use_masksomptbbc                 Z   [        U R                  R                  5      U l        [	        SU R                  5         US:X  a  [        U5        OUS:X  a  [        U5        OUS:X  a  [        U5        OUS:X  a  [        U5        OUS:X  a  [        U5        O}US:X  ai  [
        [        /n[        (       a*  UR                  [        5        UR                  [        5        [        R                  " U5        U H  nU" U5        M     O[        SU-  5      eS S S 5        g ! , (       d  f       g = f)	N	CACHE_DIRr   r   r   r   multiprocessing_defaultr`   zUnknown parallelism supplied %s)r   	__class__r7   
_cache_dirr   thread_implfork_proc_implforkserver_proc_implspawn_proc_impldefault_proc_impl_HAVE_OS_FORKr   r`   shuffle
ValueError)r3   ru   parallelismpsimpls        r   r   #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*)r   N)r   )r7   r8   r9   r:   __doc__r=   rX   r]   re   	all_impls_parfors_unsupportedparfor_implsextendr   NUMBA_NUM_THREADSmasks
mask_implsr   rR   r   rN   r   r   runnerssafe_backendsr   r;   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                   (    \ rS rSrSr\S 5       rSrg)TestParallelBackendi6  a]  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                     U R                    HN  nU R                  R                  5        H-  u  p#SU-   S-   U-   nS nU" X15      nXFl        [	        XU5        M/     MP     g )Ntest_rx   c                    ^ ^ U U4S jnU$ )Nc                    > [         R                  " 5       nUR                  (       a  SnU R                  U5        g U R	                  TTS9  g )Nz)daemonized processes cannot have children)r   )r   current_processdaemonskipTestr   )r3   selfprocr   r   ps      r   test_methodBTestParallelBackend.generate.<locals>.methgen.<locals>.test_methodJ  s<    #2#B#B#D#??#ND MM$/ ,,Tq,Ar   r&   )r   r   r   s   `` r   methgen-TestParallelBackend.generate.<locals>.methgenI  s    B '&r   )r   r   itemsr7   setattr)clsr   namer   methnamer   ry   s          r   generateTestParallelBackend.generateC  s\    A!kk//1
"Q;,t3	' T%&r* 2 !r   r&   N)r7   r8   r9   r:   r   classmethodr   r;   r&   r   r   r   r   6  s     + +r   r   c                   N    \ rS rSr\\\R                  " SS5      S.rS r	S r
Srg)	TestInSubprocessi[  F r   r   r   c                    [         R                  " U[         R                  [         R                  US9n[        R                  " [
        UR                  5      n UR                  5         UR                  5       u  pVUR                  S:w  a,  [        SUR                  < SUR                  5       < S35      eUR                  5       UR                  5       4UR                  5         $ ! UR                  5         f = f)Nstdoutstderrenvr   process failed with code : stderr follows
r   
subprocessPopenPIPEr   Timer_TEST_TIMEOUTkillr   communicate
returncodeAssertionErrordecodecancelr3   cmdliner   popentimeoutr+   errs          r   run_cmdTestInSubprocess.run_cmd`  s      (2(2%(*
 //-<		MMO((*HC1$$%%szz|56 6 ::<-NNGNNs   A=C( (C:c                     [         R                  R                  5       n[        U5      US'   [        R
                  SSU/nU R                  XC5      $ )NNUMBA_THREADING_LAYERz-mznumba.runtests)osenvironcopystrsys
executabler  )r3   testthreading_layerenv_copyr  s        r   run_test_in_separate_process-TestInSubprocess.run_test_in_separate_processs  sD    ::??$,/,@()>>4)94@||G..r   r&   N)r7   r8   r9   r:   skip_no_tbbskip_no_ompunittestskipIfbackendsr  r  r;   r&   r   r   r   r   [  s'    ""%__UB79H&/r   r   c                   <    \ rS rSrSrSr\S 5       r\S 5       rSr	g)TestSpecificBackendiz  a  
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           	         ^^
 U R                   n[        R                  nSU-   S-   U-   nU< SU< SU< 3m
UU
4S jnSU< SU< ST< 3n	[        X	[	        S5      " U" U5      5      5        g )Nr   rx   .c                 `  > U R                  TT5      u  pU R                  (       a  [        SU< SU< S35        [        R                  " SU5      nUb   U R                  UR                  S5      5        U R                  SU5        U R                  SU;  5        U R                  SU;  5        g )	Nz
stdout:
 "z"
 stderr:
 ""z\.\.\. skipped '(.*?)'r   OKFAILERROR)	r  _DEBUGprintresearchr   groupassertIn
assertTrue)r3   orz   mbackendinjected_methods       r   test_template2TestSpecificBackend._inject.<locals>.test_template  s    44_gNDA{{1a@A 		3Q7A}aggaj)MM$"OOF!O,OOG1,-r   long_running)r8   r   r7   r   r
   )r   r   r   r1  backend_guardthemodtheclsr   r3  injected_testr2  s      `      @r   _injectTestSpecificBackend._inject  sf    $--Q;$t+(.A	. ,-dG<N#M-$@A	Cr   c           	      V   U R                   R                  5        H  u  pU R                   Hv  nU R                  R	                  5        HU  nUS;   a,  US:X  a&  [
        R                  R                  S5      (       a  M5  US;   a  US:X  a  MC  U R                  X4X5        MW     Mx     M     g )N)r   r`   r   linux)r   r`   r   )	r  r   r   r   keysr  platform
startswithr:  )r   r1  r6  r   r   s        r   r   TestSpecificBackend.generate  s    &)ll&8&8&:"G__KK,,.D ??5(LL33G<<  44#{2 KK@ / % ';r   r&   N)
r7   r8   r9   r:   r   r(  r   r:  r   r;   r&   r   r   r   r   z  s8     FC C. A Ar   r   c                   l    \ rS rSrSrS\R                  R                  \5      -  r	SS\	0-  r
S	S jrSrg)
ThreadLayerTestHelperi  zH
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                 Z   Uc,  [         R                  R                  5       n[        S5      US'   [        R
                  " U[        R                  [        R                  US9n[        R                  " [        UR                  5      n UR                  5         UR                  5       u  pVUR                  S:w  a,  [        SUR                  < SUR                  5       < S35      e UR!                  5         UR                  5       UR                  5       4$ ! UR!                  5         f = f)Nr   r  r   r   r   r   r   )r  r  r  r  r   r   r   r   r   r   r   r   r  r  r  r  r  r  s          r   r  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&   r   )r7   r8   r9   r:   r   r  pathdirname__file___heretemplater  r;   r&   r   r   rC  rC    s:    
 277??8,,E, 5/-H0*r   rC  c                   j    \ rS rSrSrSr\\\R                  " SS5      S.r
\S 5       r\S 5       rSrg	)
TestThreadingLayerSelectioni  z8
Checks that numba.threading_layer() reports correctly.
Fr   r   c           	      ^   ^ U4S jnST-  n[        X[        S5      " U" U5      5      5        g )Nc                   > SnU R                   UT-  -  n[        R                  SU/n[        R                  R                  5       n[        T5      US'   U R                  X4S9u  pVU R                  (       a  [        XV5        g g )Nzif 1:
                X = np.arange(1000000.)
                Y = np.arange(1000000.)
                Z = busy_func(X, Y)
                assert numba.threading_layer() == '%s'
            -cr  r   )
rK  r  r  r  r  r  r  r  r(  r)  )r3   bodyrunmer  r   r+   r
  r1  s          r   r3  :TestThreadingLayerSelection._inject.<locals>.test_template  sr    D MMTG^4E~~tU3G**//#C+.w<C'(||G|5HC{{c r   z test_threading_layer_selector_%s	important)r   r
   )r   r1  r6  r3  r9  s    `   r   r:  #TestThreadingLayerSelection._inject  s1    	  ;WDK }!=>	@r   c                 l    U R                   R                  5        H  u  pU R                  X5        M     g r   )r  r   r:  )r   r1  r6  s      r   r   $TestThreadingLayerSelection.generate  s(    &)ll&8&8&:"GKK/ ';r   r&   N)r7   r8   r9   r:   r   r(  r  r  r  r  r  r   r:  r   r;   r&   r   r   rM  rM    sS     F""%__UB79H @ @( 0 0r   rM  c                   |    \ rS rSrS\4S jr\\S 5       5       r\\S 5       5       r	\S 5       r
\S 5       rS rS	rg
)TestThreadingLayerPriorityi  env_varc                     [         R                  R                  5       nSUS'   XS'   SU S3n[        R                  S[
        R                  " U5      /nU R                  XBS9  g)	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"
                rP  rQ  N)r  r  r  r  r  textwrapdedentr  )r3   r[  r   codecmds        r   each_env_var'TestThreadingLayerPriority.each_env_var  so     jjoo'0#$07,-) *1	 2( NNOOD!

 	S"r   c                     / SQn[         R                  " U5       H%  nSR                  U5      nU R                  U5        M'     g )Nr    )	itertoolspermutationsr   rb  )r3   r   r   r[  s       r   test_valid_env_var-TestThreadingLayerPriority.test_valid_env_var8  s9     .''0AhhqkGg& 1r   c                     SnU R                  [        5       nU R                  U5        S S S 5        S H)  nU R                  U [	        WR
                  5      5        M+     g ! , (       d  f       N>= f)Nztbb omp workqueue notvalidhere)z!THREADING_LAYER_PRIORITY invalid:zIt must be a permutation of)assertRaisesr  rb  r-  r  	exception)r3   r[  raisesmsgs       r   test_invalid_env_var/TestThreadingLayerPriority.test_invalid_env_var@  s^     3~.&g& /
C MMSEC(8(8$9:	
 /.s   A""
A0c                 8    S H  nU R                  U5        M     g )N)zomp tbb workqueuezomp workqueue tbbrb  r3   r[  s     r   test_omp#TestThreadingLayerPriority.test_ompL      AGg& Br   c                 8    S H  nU R                  U5        M     g )N)ztbb omp workqueueztbb workqueue omprr  rs  s     r   test_tbb#TestThreadingLayerPriority.test_tbbQ  rv  r   c                 8    S H  nU R                  U5        M     g )N)zworkqueue tbb ompzworkqueue omp tbbrr  rs  s     r   test_workqueue)TestThreadingLayerPriority.test_workqueueV  s    AGg& Br   r&   N)r7   r8   r9   r:   r  rb  r  r  rh  ro  rt  rx  r{  r;   r&   r   r   rZ  rZ    st    #C #B '  ' ;  ; ' ' ' ''r   rZ  c                   t    \ rS rSrSrSr\S 5       r\S 5       r	S r
\R                  " \S5      S 5       rS	rg
)TestMiscBackendIssuesi[  zD
Checks fixes for the issues with threading backends implementation
Fc                     Sn[         R                  SU/n[        R                  R	                  5       nSUS'   SUS'   U R                  X#S9  g)	z(
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"
        rP  r   r  100KOMP_STACKSIZErQ  Nr  r  r  r  r  r  r3   rS  r  r   s       r   test_omp_stack_overflow-TestMiscBackendIssues.test_omp_stack_overflowb  sN    
 >>4/jjoo',#$%OW&r   c                     Sn[         R                  SU/n[        R                  R	                  5       nSUS'   SUS'   U R                  X#S9  g)	zY
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"
        rP  r   r  1r   rQ  Nr  r  s       r   test_single_thread_tbb,TestMiscBackendIssues.test_single_thread_tbby  sO     >>4/jjoo',#$#& W&r   c                 j   Sn[         R                  SU/n[        R                  R	                  5       nSUS'   SUS'    U R                  X#S9u  pEg
! [         aW  nU R                  (       a  [        WW5        [        U5      nU R                  SU5        S	nU R                  X5         S
nAg
S
nAff = f)zG
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()
        rP  r   r  4r   rQ  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-  )	r3   rS  r  r   r+   r
  rz   e_msgrG   s	            r   +test_workqueue_aborts_on_nested_parallelismATestMiscBackendIssues.test_workqueue_aborts_on_nested_parallelism  s    & >>4/jjoo'2#$#& 	+||G|5HC 		+{{c3FEMM,e4?HMM(**		+s   A 
B2AB--B2zTest needs fork(2)c                     Sn[         R                  SU/n[        R                  R	                  5       nSUS'   SUS'   U R                  X#S9  g )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"
        rP  r   r  r  r   rQ  r  r  s       r   0test_workqueue_handles_fork_from_non_main_threadFTestMiscBackendIssues.test_workqueue_handles_fork_from_non_main_thread  sO    6 >>4/jjoo'2#$#& W&r   r&   N)r7   r8   r9   r:   r   r(  r  r  r  r  r  r  
skipUnlessr   r  r;   r&   r   r   r~  r~  [  s\     F' ', ' '0'+R (<=&' >&'r   r~  c                   Z    \ rS rSrSrSrS rS rS r\	S 5       r
S rS	 r\	S
 5       rSrg)TestForkSafetyIssuesi  zN
Checks Numba's behaviour in various situations involving GNU OpenMP and fork
Fc                 T    Sn[         R                  SU/nU R                  U5      u  p4g )Nzsif 1:
            from numba.np.ufunc import omppool
            assert omppool.openmp_vendor == 'GNU'
            rP  )r  r  r  )r3   rS  r  r+   r
  s        r   !test_check_threading_layer_is_gnu6TestForkSafetyIssues.test_check_threading_layer_is_gnu  s-     >>4/<<(Sr   c                     SnU R                   U-  n[        R                  SU/n U R                  U5      u  pEg! [         a%  nU R                  S[        U5      5         SnAgSnAff = f)zf
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()
        rP  zfailed with code -6N)rK  r  r  r  r  r-  r  )r3   rR  rS  r  r+   r
  rz   s          r   !test_par_parent_os_fork_par_child6TestForkSafetyIssues.test_par_parent_os_fork_par_child  sf    
	 $>>4/	9||G,HC 	9MM/Q88	9s   : 
A)A$$A)c                     SnU R                   U-  n[        R                  SU/nU R                  U5      u  pEU R                  (       a  [        XE5        gg)a-  
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)
        rP  NrK  r  r  r  r(  r)  r3   rR  rS  r  r+   r
  s         r   *test_par_parent_implicit_mp_fork_par_child?TestForkSafetyIssues.test_par_parent_implicit_mp_fork_par_child  sL      $>>4/<<(;;#O r   c                     SnU R                   U-  n[        R                  SU/nU R                  U5      u  pEU R                  (       a  [        XE5        gg)a-  
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)
        rP  Nr  r  s         r   *test_par_parent_explicit_mp_fork_par_child?TestForkSafetyIssues.test_par_parent_explicit_mp_fork_par_child-  sL    " $>>4/<<(;;#O r   c                     SnU R                   U-  n[        R                  SU/nU R                  U5      u  pEU R                  (       a  [        XE5        gg)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)
        rP  Nr  r  s         r   -test_par_parent_mp_spawn_par_child_par_parentBTestForkSafetyIssues.test_par_parent_mp_spawn_par_child_par_parentP  sL    : $>>4/<<(;;#O r   c                     SnU R                   U-  n[        R                  SU/nU R                  U5      u  pEU R                  (       a  [        XE5        gg)z
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")
        rP  Nr  r  s         r   =test_serial_parent_implicit_mp_fork_par_child_then_par_parentRTestForkSafetyIssues.test_serial_parent_implicit_mp_fork_par_child_then_par_parent|  L    2 $>>4/<<(;;#O r   c                     SnU R                   U-  n[        R                  SU/nU R                  U5      u  pEU R                  (       a  [        XE5        gg)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")
        rP  Nr  r  s         r   =test_serial_parent_explicit_mp_fork_par_child_then_par_parentRTestForkSafetyIssues.test_serial_parent_explicit_mp_fork_par_child_then_par_parent  r  r   r&   N)r7   r8   r9   r:   r   r(  r  r  r  r   r  r  r  r  r;   r&   r   r   r  r    sS     F)9,B    D*X'R & &r   r  c                   8    \ rS rSrSr\S 5       r\S 5       rSrg)TestTBBSpecificIssuesi  Fc                     Sn[         R                  SU/nU R                  U5      u  p4SnU R                  XT5        U R                  (       a  [        SU5        [        SU5        g g )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()
        rP  z9Attempted to fork from a non-main thread, the TBB libraryOUT:ERR:)r  r  r  r-  r(  r)  )r3   rS  r  r+   r
  msg_heads         r   test_fork_from_non_main_thread4TestTBBSpecificIssues.test_fork_from_non_main_thread  s]    64l >>4/<<(Nh$;;&#&# r   c                    U R                  5         SnSR                  SU5      n[        R                  SU/n[        R
                  R                  5       nSUS'   U R                  X4S9u  pVX;   a  U R                  S5        OU R                  S	U5        U R                  (       a  [        S
U5        [        SU5        g g )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_COMPILERSrP  r   r  rQ  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)  )r3   r  rS  r  r   r+   r
  s          r   &test_lifetime_of_task_scheduler_handle<TestTBBSpecificIssues.test_lifetime_of_task_scheduler_handle0  s     	))+ 6KV *,<=W 	Z >>4/jjoo',#$<<<1"MMOPMM)S);;&#&# r   r&   N)	r7   r8   r9   r:   r(  r   r  r  r;   r&   r   r   r  r    s4     FX Xt _ _r   r  c                   4    \ rS rSrSrS r\S 5       rS rSr	g)TestInitSafetyIssuesi  Fc                    [         R                  " U[         R                  [         R                  S9n[        R                  " [
        UR                  5      n UR                  5         UR                  5       u  pEUR                  S:w  a,  [        SUR                  < SUR                  5       < S35      e UR                  5         UR                  5       UR                  5       4$ ! UR                  5         f = f)N)r   r   r   r   r   r   r   )r3   r  r  r	  r+   r
  s         r   r  TestInitSafetyIssues.run_cmd  s      (2(2: //-<	MMO((*HC1$$%%szz|56 6 %
 NNzz|SZZ\)) NNs   AC( (C:c                 H   [         R                  R                  [         R                  R                  [        5      S5      n[
        R                  U/nU R                  U5      u  p4U R                  SU5        U R                  (       a  [        SU5        [        SU5        g g )Nzorphaned_semaphore_usecase.pyzleaked semaphorer  r  )r  rG  r   rH  rI  r  r  r  assertNotInr(  r)  )r3   	test_filer  r+   r
  s        r   test_orphaned_semaphore,TestInitSafetyIssues.test_orphaned_semaphore  sz    
 GGLL!:!@B	>>9-<<( 	+S1;;&#&# r   c                 H   S H  n [         R                  " U5        Sn[        R                  SUR                  U5      /nU R                  U5      u  pEU R                  (       a  [        SU5        [        SU5        U R                  X5        M     g ! [         a     M  f = f)N)r   r   r   zimport numba; import multiprocessing;multiprocessing.set_start_method('{}');print(multiprocessing.get_context().get_start_method())rP  r  r  )
r   r   r   r  r  formatr  r(  r)  r-  )r3   methra  r  r+   r
  s         r   test_lazy_lock_init(TestInitSafetyIssues.test_lazy_lock_init  s     4D++D1MC ~~tSZZ-=>G||G,HC{{fc"fc"MM$$ 4
  s   B
B! B!r&   N)
r7   r8   r9   r:   r(  r  r   r  r  r;   r&   r   r   r  r    s'     F*"   %r   r  c                       \ rS rSrS rSrg)TestOpenMPVendorsi  c                     [        5       nSUS'   SUS'   SUS'   UR                  5        HK  n[        R                  R	                  U5      (       d  M)  U R                  X   [        R                  5        MM     g)z.
Checks the OpenMP vendor strings are correct
MSwin32Intelr   r   r=  N)dictr>  r  r?  r@  assertEqualr   openmp_vendor)r3   rG   ks      r   test_vendorsTestOpenMPVendors.test_vendors  sh     6 $! A||&&q))  g.C.CD !r   r&   N)r7   r8   r9   r:   r  r;   r&   r   r   r  r    s    Er   r  __main__)cr   rm   rf  r   r  r`   r*  r   r  r^  r   r  numpyr   numbar   r   r   r   numba.tests.supportr   r   r	   r
   r   r   rk   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_LAPACKr  r  r  r  _gnuompskip_unless_gnu_ompr?  r@  _windows_osxmaxsize_32bitr   r   r   r#   r)   r,   objectr.   r=   rN   rX   r]   re   r{   r   Thread_thread_classr   r   r   r   r   r   r   r   r   THREADING_LAYER_specific_backendsr   r   r   r   rC  rM  rZ  r~  r  r  r  r  r7   mainr&   r   r   <module>r     s      	  	  
     > >G G  :   #%
E!#&N&N%L
 !!.2NO!!.2KL

;W22e;))'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MMO y%  N  N  Ls6   %L ;L L+ LLL('L(+L76L7