From d0873d2c72f26ad17cfe15344edcc30ec6772535 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 17 Feb 2021 09:56:43 +1100 Subject: [PATCH] Rebase against a55a37d1dae2231d8dec9f3191449f89be0b10dc. --- ...-versions-of-RtlEnterCriticalSection.patch | 10 ++-- ...-Improve-heap-allocation-performance.patch | 50 +++++++++---------- ...thread-id-alerts-on-top-of-Mach-sema.patch | 22 ++++---- ...tore-TEB-to-x18-on-aarch-64-on-retur.patch | 14 +++--- patches/patchinstall.sh | 2 +- staging/upstream-commit | 2 +- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch b/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch index 5ee1a6a7..ba879117 100644 --- a/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch +++ b/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch @@ -1,4 +1,4 @@ -From fea92ad5c12ddb8d0a4d2363f21afe9c199359d1 Mon Sep 17 00:00:00 2001 +From b9815e86e026c431050253146177f5c624a28756 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 5 Aug 2017 03:38:38 +0200 Subject: [PATCH] ntdll: Add inline versions of RtlEnterCriticalSection / @@ -9,7 +9,7 @@ Subject: [PATCH] ntdll: Add inline versions of RtlEnterCriticalSection / 1 file changed, 34 insertions(+) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 92fcde95a8a..51a9069e290 100644 +index 67696f80db3..f25d8adc217 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -26,6 +26,7 @@ @@ -17,10 +17,10 @@ index 92fcde95a8a..51a9069e290 100644 #include "winternl.h" #include "unixlib.h" +#include "wine/debug.h" - #include "wine/server.h" #include "wine/asm.h" -@@ -103,6 +104,39 @@ extern int ntdll_wcstoumbs( const WCHAR* src, DWORD srclen, char* dst, DWORD dst + #define DECLARE_CRITICAL_SECTION(cs) \ +@@ -96,6 +97,39 @@ extern int ntdll_wcstoumbs( const WCHAR* src, DWORD srclen, char* dst, DWORD dst extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args ) DECLSPEC_HIDDEN; extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args ) DECLSPEC_HIDDEN; @@ -61,5 +61,5 @@ index 92fcde95a8a..51a9069e290 100644 enum loadorder -- -2.27.0 +2.30.0 diff --git a/patches/ntdll-Heap_Improvements/0002-ntdll-Improve-heap-allocation-performance.patch b/patches/ntdll-Heap_Improvements/0002-ntdll-Improve-heap-allocation-performance.patch index 27e53ada..667e1b39 100644 --- a/patches/ntdll-Heap_Improvements/0002-ntdll-Improve-heap-allocation-performance.patch +++ b/patches/ntdll-Heap_Improvements/0002-ntdll-Improve-heap-allocation-performance.patch @@ -1,4 +1,4 @@ -From 1b79a7d8eb8c813cca81916eda14090a15b93290 Mon Sep 17 00:00:00 2001 +From 715e01ee3d9aae413a496075995a607e04f7cf80 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 22 Jul 2017 07:21:45 +0200 Subject: [PATCH] ntdll: Improve heap allocation performance. (v2) @@ -8,7 +8,7 @@ Subject: [PATCH] ntdll: Improve heap allocation performance. (v2) 1 file changed, 210 insertions(+), 96 deletions(-) diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c -index 4fe11fe2b48..de33fcce4bb 100644 +index 7939b2c5727..96bd5f2081d 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -3,6 +3,7 @@ @@ -25,9 +25,9 @@ index 4fe11fe2b48..de33fcce4bb 100644 #include "wine/list.h" +#include "wine/rbtree.h" #include "wine/debug.h" - #include "wine/server.h" -@@ -56,7 +58,11 @@ typedef struct tagARENA_FREE + WINE_DEFAULT_DEBUG_CHANNEL(heap); +@@ -55,7 +57,11 @@ typedef struct tagARENA_FREE { DWORD size; /* Block size; must be the first field */ DWORD magic; /* Magic number */ @@ -40,7 +40,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 } ARENA_FREE; typedef struct -@@ -69,9 +75,11 @@ typedef struct +@@ -68,9 +74,11 @@ typedef struct DWORD magic; /* these must remain at the end of the structure */ } ARENA_LARGE; @@ -55,7 +55,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 #define ARENA_LARGE_SIZE 0xfedcba90 /* magic value for 'size' field in large blocks */ /* Value for arena 'magic' field */ -@@ -89,6 +97,8 @@ typedef struct +@@ -88,6 +96,8 @@ typedef struct #define LARGE_ALIGNMENT 16 /* large blocks have stricter alignment */ #define ARENA_OFFSET (ALIGNMENT - sizeof(ARENA_INUSE)) @@ -64,7 +64,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 C_ASSERT( sizeof(ARENA_LARGE) % LARGE_ALIGNMENT == 0 ); #define ROUND_SIZE(size) ((((size) + ALIGNMENT - 1) & ~(ALIGNMENT-1)) + ARENA_OFFSET) -@@ -97,9 +107,7 @@ C_ASSERT( sizeof(ARENA_LARGE) % LARGE_ALIGNMENT == 0 ); +@@ -96,9 +106,7 @@ C_ASSERT( sizeof(ARENA_LARGE) % LARGE_ALIGNMENT == 0 ); #define NOISY 0 /* Report all errors */ /* minimum data size (without arenas) of an allocated block */ @@ -75,7 +75,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /* minimum size that must remain to shrink an allocated block */ #define HEAP_MIN_SHRINK_SIZE (HEAP_MIN_DATA_SIZE+sizeof(ARENA_FREE)) /* minimum size to start allocating large blocks */ -@@ -108,23 +116,14 @@ C_ASSERT( sizeof(ARENA_LARGE) % LARGE_ALIGNMENT == 0 ); +@@ -107,23 +115,14 @@ C_ASSERT( sizeof(ARENA_LARGE) % LARGE_ALIGNMENT == 0 ); #define HEAP_TAIL_EXTRA_SIZE(flags) \ ((flags & HEAP_TAIL_CHECKING_ENABLED) || RUNNING_ON_VALGRIND ? ALIGNMENT : 0) @@ -107,7 +107,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 struct tagHEAP; -@@ -157,9 +156,17 @@ typedef struct tagHEAP +@@ -162,9 +161,17 @@ typedef struct tagHEAP DWORD pending_pos; /* Position in pending free requests ring */ ARENA_INUSE **pending_free; /* Ring buffer for pending free requests */ RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */ @@ -126,7 +126,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 #define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24))) #define HEAP_DEF_SIZE 0x110000 /* Default heap size = 1Mb + 64Kb */ -@@ -176,6 +183,13 @@ static HEAP *processHeap; /* main process heap */ +@@ -181,6 +188,13 @@ static HEAP *processHeap; /* main process heap */ static BOOL HEAP_IsRealArena( HEAP *heapPtr, DWORD flags, LPCVOID block, BOOL quiet ); @@ -140,7 +140,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /* mark a block of memory as free for debugging purposes */ static inline void mark_block_free( void *ptr, SIZE_T size, DWORD flags ) { -@@ -297,20 +311,6 @@ static void subheap_notify_free_all(SUBHEAP const *subheap) +@@ -302,20 +316,6 @@ static void subheap_notify_free_all(SUBHEAP const *subheap) #endif } @@ -161,7 +161,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /* get the memory protection type to use for a given heap */ static inline ULONG get_protection_type( DWORD flags ) { -@@ -338,13 +338,31 @@ static void HEAP_Dump( HEAP *heap ) +@@ -343,13 +343,31 @@ static void HEAP_Dump( HEAP *heap ) TRACE( "Next: %p Sub-heaps:", LIST_ENTRY( heap->entry.next, HEAP, entry ) ); LIST_FOR_EACH_ENTRY( subheap, &heap->subheap_list, SUBHEAP, entry ) TRACE( " %p", subheap ); @@ -199,7 +199,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 LIST_FOR_EACH_ENTRY( subheap, &heap->subheap_list, SUBHEAP, entry ) { -@@ -359,11 +377,32 @@ static void HEAP_Dump( HEAP *heap ) +@@ -364,11 +382,32 @@ static void HEAP_Dump( HEAP *heap ) if (*(DWORD *)ptr & ARENA_FLAG_FREE) { ARENA_FREE *pArena = (ARENA_FREE *)ptr; @@ -237,7 +237,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); arenaSize += sizeof(ARENA_FREE); freeSize += pArena->size & ARENA_SIZE_MASK; -@@ -471,20 +510,19 @@ static HEAP *HEAP_GetPtr( +@@ -476,20 +515,19 @@ static HEAP *HEAP_GetPtr( */ static inline void HEAP_InsertFreeBlock( HEAP *heap, ARENA_FREE *pArena, BOOL last ) { @@ -266,7 +266,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 } -@@ -495,7 +533,19 @@ static inline void HEAP_InsertFreeBlock( HEAP *heap, ARENA_FREE *pArena, BOOL la +@@ -500,7 +538,19 @@ static inline void HEAP_InsertFreeBlock( HEAP *heap, ARENA_FREE *pArena, BOOL la */ static inline void HEAP_DeleteFreeBlock( HEAP *heap, ARENA_FREE *pArena ) { @@ -287,7 +287,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 } -@@ -875,6 +925,15 @@ static BOOL validate_large_arena( HEAP *heap, const ARENA_LARGE *arena, BOOL qui +@@ -880,6 +930,15 @@ static BOOL validate_large_arena( HEAP *heap, const ARENA_LARGE *arena, BOOL qui } @@ -303,7 +303,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /*********************************************************************** * HEAP_CreateSubHeap */ -@@ -882,7 +941,6 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, +@@ -887,7 +946,6 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, SIZE_T commitSize, SIZE_T totalSize ) { SUBHEAP *subheap; @@ -311,7 +311,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 unsigned int i; if (!address) -@@ -943,17 +1001,21 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, +@@ -948,17 +1006,21 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, subheap->headerSize = ROUND_SIZE( sizeof(HEAP) ); list_add_head( &heap->subheap_list, &subheap->entry ); @@ -343,7 +343,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /* Initialize critical section */ -@@ -996,6 +1058,34 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, +@@ -1001,6 +1063,34 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, } @@ -378,7 +378,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 /*********************************************************************** * HEAP_FindFreeBlock * -@@ -1005,26 +1095,41 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, +@@ -1010,26 +1100,41 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, SUBHEAP **ppSubHeap ) { @@ -432,7 +432,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 } /* If no block was found, attempt to grow the heap */ -@@ -1070,13 +1175,10 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, +@@ -1075,13 +1180,10 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, SIZE_T size, */ static BOOL HEAP_IsValidArenaPtr( const HEAP *heap, const ARENA_FREE *ptr ) { @@ -446,7 +446,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 return FALSE; } -@@ -1088,7 +1190,7 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) +@@ -1093,7 +1195,7 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) { DWORD flags = subheap->heap->flags; SIZE_T size; @@ -455,7 +455,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 char *heapEnd = (char *)subheap->base + subheap->size; /* Check for unaligned pointers */ -@@ -1105,7 +1207,8 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) +@@ -1110,7 +1212,8 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) return FALSE; } /* Check size flags */ @@ -465,7 +465,7 @@ index 4fe11fe2b48..de33fcce4bb 100644 (pArena->size & ARENA_FLAG_PREV_FREE)) { ERR("Heap %p: bad flags %08x for free arena %p\n", -@@ -1119,34 +1222,45 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) +@@ -1124,34 +1227,45 @@ static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) ERR("Heap %p: bad size %08lx for free arena %p\n", subheap->heap, size, pArena ); return FALSE; } @@ -520,5 +520,5 @@ index 4fe11fe2b48..de33fcce4bb 100644 subheap->heap, prev, pArena ); return FALSE; -- -2.27.0 +2.30.0 diff --git a/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch b/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch index d162fb3b..67a71e9a 100644 --- a/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch +++ b/patches/ntdll-NtAlertThreadByThreadId/0007-ntdll-Implement-thread-id-alerts-on-top-of-Mach-sema.patch @@ -1,4 +1,4 @@ -From 4c58c278a16e77650b1a3626df6e43cb603089e2 Mon Sep 17 00:00:00 2001 +From ad509d2c9f4d49b87221929f65e4e35568ad33c2 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 31 Aug 2020 23:03:34 -0500 Subject: [PATCH] ntdll: Implement thread-id alerts on top of Mach semaphores @@ -12,10 +12,10 @@ Signed-off-by: Zebediah Figura 3 files changed, 56 insertions(+) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c -index 05a478ae464..377a34c0824 100644 +index 0c7fea3bd4d..0fee8f3099d 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c -@@ -2144,6 +2144,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) +@@ -2357,6 +2357,10 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) if (teb->ClientId.UniqueThread == tid) { pthread_rwlock_unlock( &teb_list_lock ); @@ -26,7 +26,7 @@ index 05a478ae464..377a34c0824 100644 #ifdef __linux__ if (use_futexes()) { -@@ -2155,6 +2159,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) +@@ -2368,6 +2372,7 @@ NTSTATUS WINAPI NtAlertThreadByThreadId( HANDLE tid ) #endif NtSetEvent( thread_data->tid_alert_event, NULL ); return STATUS_SUCCESS; @@ -34,7 +34,7 @@ index 05a478ae464..377a34c0824 100644 } } -@@ -2192,6 +2197,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG +@@ -2405,6 +2410,44 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG { TRACE( "%p %s\n", address, debugstr_timeout( timeout ) ); @@ -79,7 +79,7 @@ index 05a478ae464..377a34c0824 100644 #ifdef __linux__ if (use_futexes()) { -@@ -2227,6 +2270,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG +@@ -2440,6 +2483,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG } #endif return NtWaitForSingleObject( ntdll_get_thread_data()->tid_alert_event, FALSE, timeout ); @@ -104,11 +104,11 @@ index bb55b3d29ed..05157e24ace 100644 pthread_attr_init( &pthread_attr ); pthread_attr_setstack( &pthread_attr, teb->DeallocationStack, diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index 7e733052c87..dc1c379c790 100644 +index 429b1e767ff..0b5cf8a3c4f 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h -@@ -26,6 +26,10 @@ - #include "unixlib.h" +@@ -27,6 +27,10 @@ + #include "wine/server.h" #include "wine/list.h" +#ifdef __APPLE__ @@ -118,7 +118,7 @@ index 7e733052c87..dc1c379c790 100644 #ifdef __i386__ static const enum cpu_type client_cpu = CPU_x86; #elif defined(__x86_64__) -@@ -57,10 +61,14 @@ struct ntdll_thread_data +@@ -60,10 +64,14 @@ struct ntdll_thread_data struct list entry; /* entry in TEB list */ PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ @@ -134,5 +134,5 @@ index 7e733052c87..dc1c379c790 100644 C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); -- -2.29.2 +2.30.0 diff --git a/patches/ntdll-aarch-TEB/0002-ntdll-Always-restore-TEB-to-x18-on-aarch-64-on-retur.patch b/patches/ntdll-aarch-TEB/0002-ntdll-Always-restore-TEB-to-x18-on-aarch-64-on-retur.patch index 3c358a0b..78206b21 100644 --- a/patches/ntdll-aarch-TEB/0002-ntdll-Always-restore-TEB-to-x18-on-aarch-64-on-retur.patch +++ b/patches/ntdll-aarch-TEB/0002-ntdll-Always-restore-TEB-to-x18-on-aarch-64-on-retur.patch @@ -1,4 +1,4 @@ -From c9d1b1c5498a893ed99803dbcead591ff3f9e953 Mon Sep 17 00:00:00 2001 +From 3a0372bf303cbbfbb94f23455758b6020f038241 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Wed, 16 Aug 2017 23:48:40 +0300 Subject: [PATCH] ntdll: Always restore TEB to x18 on aarch 64 on return from @@ -20,12 +20,12 @@ Signed-off-by: Martin Storsjo 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index cec8e114e14..d09948c51aa 100644 +index f54e25fcc5c..87ffc74062b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c -@@ -2135,7 +2135,13 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, +@@ -2073,7 +2073,13 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, - if (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) + if (image_info->u.s.WineBuiltin) { - if (TRACE_ON(relay)) RELAY_SetupDLL( *module ); +#ifdef __aarch64__ @@ -39,10 +39,10 @@ index cec8e114e14..d09948c51aa 100644 else { diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c -index e1596312491..63ae0d8ec41 100644 +index be2dc833377..e29496a8c7a 100644 --- a/dlls/ntdll/relay.c +++ b/dlls/ntdll/relay.c -@@ -702,8 +702,12 @@ static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, +@@ -691,8 +691,12 @@ static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, { unsigned int nb_args; void *func = relay_trace_entry( descr, idx, stack, &nb_args ); @@ -56,5 +56,5 @@ index e1596312491..63ae0d8ec41 100644 } -- -2.28.0 +2.30.0 diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index cc8e7f4c..0c4b3cac 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -51,7 +51,7 @@ usage() # Get the upstream commit sha upstream_commit() { - echo "a9c8196e97ec255f4f69d005ea1cbf8fcf2537e8" + echo "a55a37d1dae2231d8dec9f3191449f89be0b10dc" } # Show version information diff --git a/staging/upstream-commit b/staging/upstream-commit index e14fcff6..f431e26e 100644 --- a/staging/upstream-commit +++ b/staging/upstream-commit @@ -1 +1 @@ -a9c8196e97ec255f4f69d005ea1cbf8fcf2537e8 +a55a37d1dae2231d8dec9f3191449f89be0b10dc