+
    Ki3  c                   sL   R t ^ RIt^ RIt^ RIt^ RItRt^ RIHt  ! R R]P                  4      t	R t
R^R^R^R^R^R^R^R^/tR tR tR tR	 tR
 tR t]R 4       t]R 4       tRRRRRRRRRRRRRRRR/tR t ! R R]P                  4      tR t]R 4       t]R 4       tR# )u
  Module for detecting the availability of the Linux futex
FUTEX_WAIT_MULTIPLE operation, or the Linux futex2 syscalls.

Either of these is required for fsync to work in Wine. Fsync is an
alternative implementation of the Windows synchronization primitives
that are used to guard data from being accessed by multiple threads
concurrently (which would be A Bad Thing™).

Fsync improves upon the previous implementation in Wine of these
primitives, known as esync, which in turn improved upon the original
implementation known as "Server-side synchronization".

The original implementation used a wineserver call for each
synchronization operation, which required multiple context switches per
operation.

Esync instead used file descriptors for synchronization, which can be
passed around between processes and therefore allowed synchronization
to happen directly between the processes involved, instead of going
through the wineserver. This made the synchronization operations
faster and improved performance of games a bit.
A problem with this implementation was that each created synchronization
object required one file descriptor, and there is only a limited amount
of these available for each process. Some games would run out of
available file descriptors, and would stop working. This has been partly
mitigated by raising the per-process file descriptor limit, but there
are also games that leak synchronization objects continuously while
running, and would eventually run out despite the raised limits.

Fsync improved on esync by not requiring a file descriptor for each
created synchronization object, and instead using the Linux kernel's
futex interface for synchronizations. This matches Windows's
implementation more closely and mitigated all the file descriptor
related issues of esync. However, since the default futex interface was
insufficient for implementing all required synchronization operations,
a patch to the Linux kernel was needed, which usually meant that users
needed to compile their own Linux kernel with the patch, or install a
kernel provided by a third-party. It was attempted to get the kernel
patch into the mainline Linux kernel, but it didn't get accepted.

Instead, patches were written that would add a new set of system calls
which extend the original futex system calls, dubbed "futex2", and the
Wine fsync code was adjusted to make use of these new system calls.
The new Wine fsync code is backwards-compatible with the old futex
patch, therefore it makes sense for now to detect the presence of
either patch in the running kernel. The detection of the old patch
can probably be removed when the new patch is merged and in a stable
Linux release.

This module's code is based on https://gist.github.com/openglfreak/715d5ab5902497378f1996061dbbf8ec
N)cache_singlec                   sV    ] tR t^@tRtRtR]P                  3R]P                  3.tRt	R# )timespeczLinux kernel compatible timespec type.

Fields:
    tv_sec: The whole seconds of the timespec.
    tv_nsec: The nanoseconds of the timespec.
Ztv_secZtv_nsec N)
__name__
__module____qualname____firstlineno____doc__	__slots__ctypesc_long_fields___static_attributes__r       ;/usr/lib/python3.14/site-packages/lutris/util/wine/fsync.pyr   r   @   s-     I	6==!	FMM"Hr   r   c           	      s   \         P                  ! \         P                  4      ^,          p \        P                  ! RR\        V4      ,           RRRRR3\        P                  \        P                  \        P                  RRR	7      ;_uu_ 4       pVP                  R
V ,           R,           4      w  r4RRR4       XP                  '       d   \        RT ,           R,           X4      hX'       g   \        RT ,           R,           4      hTP                  4       R,          pTR8X  d(   \        RT ,           R,           T ,           R,           4      h \        T4      #   + '       g   i     L; i  \         d    p\        RT ,           R,           4      ThRp?ii ; i  \         d5   p\        RT ,           R,           T ,           R,           T,           4      ThRp?ii ; i)i   Zcppz-mz-Ez-Pz-xZcZ-T)ZstdinstdoutstderrZ	close_fdsZuniversal_newlinesz#include <sys/syscall.h>
__NR_Z
Nzfailed to determine z1 syscall number: cpp not installed or not in PATHz/ syscall number: cpp returned nonzero exit codez# syscall number: no output from cppZ
__NR_futexz syscall number: __NR_z not expandedz not a valid number: )r	   sizeofc_void_p
subprocessZPopenZstrZPIPEZcommunicateZFileNotFoundErrorRuntimeErrorZ
returncodeZ
splitlinesZintZ
ValueError)Zsyscall_namebitsZpopenr   r   ZexZ	last_lines   &      r   _get_syscall_nr_from_headersr   O   s   ==)A-DD3t9$dD$SA//????#
 
 "../PS_/_bf/fgNF
 "\14eegm
 	
 1L@Chhii!!#B'IL "\14LL|[^mm
 	
9~=
 
  "\14gg
	,  "\1 5 "#%<=?HI
 	sN   A%E- "E4E- 
F E*	%E- *E- -F8FFG%/GGc                     \         P                  ! \         P                  4      ^,          p  \        \        P
                  ! 4       ^,          V 3,          #   \         d     Mi ; i\        R4      # )zGet the syscall number of the Linux futex() syscall.

Returns:
    The futex() syscall number.

Raises:
    RuntimeError: When the syscall number could not be determined.
Zfutex)r	   r   r   _NR_FUTEX_PER_ARCHosunameKeyErrorr   r       r   _get_futex_syscall_nrr      sY     ==)A-D!288:a=$"788  (00   (A A$#A$c                 sj    \        V R 4      ;'       d!    \        V R4      ;'       d    \        V R4      # )Z_b_base_Z_b_needsfree_Z_objectsZhasattrZobj   &r   _is_ctypes_objr$      s/    3
#bb_(Ebb'RUWaJbbr   c                 sB    \        V R 4      ;'       d    \        V R4      # )Z_type_Zcontentsr!   r"   r#   r   _is_ctypes_obj_pointerr%      s    3!>>gc:&>>r   c                 s    V f   R # \        V 4      '       d*   \        V 4      '       d   V # \        P                  ! V 4      # \	        V 4      p V ^ ,          P
                  \        V 4      ,          ! V !  # )N)r$   r%   r	   ZpointerZtupleZ	__class__Zlenr"   r#   r   _coerce_to_pointerr&      s[    
{c!#&&J~~c""
*CFs3x'#..r   c                 s  aa \         P                  ! RRR7      P                  o\         P                  \         P                  \         P
                  \         P
                  \         P                  ! \        4      \         P                  \         P
                  3Sn        \         P
                  Sn	        \        4       oVV3R lp V # )a  Create a function that can be used to execute the Linux futex()
syscall.

Returns:
    A proxy function for the Linux futex() syscall.

Raises:
    AttributeError: When the libc has no syscall() function.
    RuntimeError: When the syscall number could not be determined.
NTZ	use_errnoc           
     s   < S! S\        V 4      TT\        T;'       g    \        4       4      \        V4      V4      pYfR8X  d   \        P                  ! 4       3# ^ 3# )a\  Invoke the Linux futex() syscall with the provided arguments.

Args:
    See the description of the futex() syscall for the parameter
    meanings.
    `uaddr` and `uaddr2` are automatically converted to pointers.
    If timeout is None, a zero timeout is passed.

Returns:
    A tuple of the return value of the syscall and the error code
    in case an error occurred.

Raises:
    AttributeError: When the libc has no syscall() function.
    RuntimeError: When the syscall number could not be determined.
    TypeError: If `uaddr` or `uaddr2` is not a pointer and can't be
        converted into one.
r   )r&   r   r	   	get_errno)	uaddrZfutex_opvaltimeoutZuaddr2Zval3errorfutex_syscallfutex_syscall_nrs	   &&&&&& r   _futex_syscallZ*_get_futex_syscall.<locals>._futex_syscall   s_    & u%w44(*5v&
 b[v'')@@a@@r   )r	   CDLLsyscallr
   r   Zc_intPOINTERr   argtypesrestyper   )r/   r-   r.       @@r   _get_futex_syscallr6      s     KK5==Mx M #LLM,.A< r   c                s    V ! R^^ RR^ 4      pV^,          \         P                  8w  d   ^# V ! R^^ RR^ 4      pV^,          \         P                  8w  d   ^# R# )zDetects which (if any) futex opcode is used for the
FUTEX_WAIT_MULTIPLE operation on this kernel.

Returns:
    The opcode number, or None if the operation is not supported.
N)errnoENOSYS)r-   rets   & r   _get_futex_wait_multiple_opr:      sU     b!T4
3C
1v
b!T4
3C
1vr   c                 s^     \        \        4       4      RJ#   \        \        3 d     R# i ; i)zChecks whether the Linux futex FUTEX_WAIT_MULTIPLE operation is
supported on this kernel.

Returns:
    Whether this kernel supports the FUTEX_WAIT_MULTIPLE operation.
NF)r:   r6   AttributeErrorr   r   r   r    is_futex_wait_multiple_supportedr<      s2    *+=+?@LLL) s    ,,c                 s,    R Ff  p \        RV ,           R4      ;_uu_ 4       pVP                  4       P                  4       P                  4       '       g    RRR4        R#  RRR4       Kh  	  R#   + '       g   i     K}  ; i  \         d     R# i ; i)zChecks whether the Linux futex2 syscall is supported on this
kernel.

Returns:
    Whether this kernel supports the futex2 syscall.
z/sys/kernel/futex2/ZrbNFT)ZwaitZwaitvZwake)ZopenZreadlineZstripZisdigitZOSError)ZfilenameZfiles     r   is_futex2_supportedr=     s~    1H+h6==}},,.6688  >=8 >= 2  >==  s.    B 4A0	B "B 0B;	B BBi  c                 r   )zGet the syscall number of the Linux futex_waitv() syscall.

Returns:
    The futex_waitv() syscall number.

Raises:
    RuntimeError: When the syscall number could not be determined.
futex_waitv)r	   r   r   _NR_FUTEX_WAITV_PER_ARCHr   r   r   r   r   r   r   _get_futex_waitv_syscall_nrr@   '  sY     ==)A-D'A(=>>  (66r    c                   sp    ] tR tRtRtRtR]P                  3R]P                  3R]P                  3.t
RtR# )r>   i;  zLinux kernel compatible futex_waitv type.

Fields:
    val: The expected value.
    uaddr: The address to wait for.
    flags: The type and size of the futex.
r*   r)   flagsr   N)r   r   r   r   r   r   r	   Zc_uint64r   c_uintr   r   r   r   r   r>   r>   ;  s9     I	 	&//"	&-- Hr   r>   c                 sf  aa \         P                  ! RRR7      P                  o\         P                  \         P                  ! \
        4      \         P                  \         P                  \         P                  ! \        4      3Sn        \         P                  Sn	        \        4       oVV3R lp V # )a  Create a function that can be used to execute the Linux
futex_waitv() syscall.

Returns:
    A proxy function for the Linux futex_waitv() syscall.

Raises:
    AttributeError: When the libc has no syscall() function.
    RuntimeError: When the syscall number could not be determined.
NTr'   c           	     s~   < S! S\        V 4      W\        V4      4      pYDR8X  d   \        P                  ! 4       3# ^ 3# )aS  Invoke the Linux futex_waitv() syscall with the provided
arguments.

Args:
    See the description of the futex_waitv() syscall for the
    parameter meanings.
    `waiters` is automatically converted to a pointer.
    If timeout is None, a zero timeout is passed.

Returns:
    A tuple of the return value of the syscall and the error code
    in case an error occurred.

Raises:
    AttributeError: When the libc has no syscall() function.
    RuntimeError: When the syscall number could not be determined.
    TypeError: If `waiters` is not a pointer and can't be
        converted into one.
r   )r&   r	   r(   )ZwaitersZ
nr_futexesrA   r+   r,   futex_waitv_syscallfutex_waitv_syscall_nrs   &&&& r   _futex_waitv_syscallZ6_get_futex_waitv_syscall.<locals>._futex_waitv_syscallc  sG    ( $"$6w$?TfgnTo
 b[v'')@@a@@r   )r	   r0   r1   r
   r2   r>   rB   r   r3   r4   r@   )rE   rC   rD   r5   r   _get_futex_waitv_syscallrF   L  sz     !++dd;CC{#x $  #)--8:A2  r   c                 s     \        4       ! R^ ^ R4      p V ^,          \        P                  8g  #   \        \        3 d     R# i ; i)zChecks whether the Linux 5.16 futex_waitv syscall is supported on
this kernel.

Returns:
    Whether this kernel supports the futex_waitv syscall.
NF)rF   r7   r8   r;   r   )r9   r   r   is_futex_waitv_supportedrG     sD    &(q!T:1v%%L) s   ,/ AAc                 sr    \        4       '       d   R# \        4       '       d   R# \        4       '       d   R# R# )zChecks whether the FUTEX_WAIT_MULTIPLE operation, the futex2
syscalls, or the futex_waitv syscall is supported on this kernel.

Returns:
    The result of the check.
TF)rG   r=   r<   r   r   r   get_fsync_supportrH     s+      !!'))r   )rH   )Zi386    )Zi686rI   )x86_64rI   )rJ   @   )Zaarch64rK   )Z
aarch64_berK   )Zarmv8brI   )Zarmv8lrI   )r   r	   r7   r   r   Z__all__Zlutris.utilr    Z	Structurer   r   r   r   r$   r%   r&   r6   r:   r<   r=   r?   r@   r>   rF   rG   rH   r   r   r   <module>rL      s*  2h   	 
  $v 'Z ##CCSCC	 1&c?
/7t  
 
  ( ##CCSCC	 7(&"" "0 f    r   