ReactOS 0.4.16-dev-2208-g6350669
fiber.c File Reference
#include <stdarg.h>
#include <ntstatus.h>
#include <winternl.h>
#include "wine/test.h"
#include <winuser.h>
Include dependency graph for fiber.c:

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 
#define X(f)   p##f = (void*)GetProcAddress(hKernel32, #f);
 
#define X(f)   p##f = (void*)GetProcAddress(hntdll, #f);
 
#define FLS_TEST_INDEX_COUNT   4096
 
#define check_current_actctx_is(e, t)   check_current_actctx_is_(__LINE__, e, t)
 

Functions

static LPVOID (WINAPI *pCreateFiber)(SIZE_T
 
static BOOL (WINAPI *pConvertFiberToThread)(void)
 
static void (WINAPI *pSwitchToFiber)(LPVOID)
 
static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION)
 
static PVOID (WINAPI *pFlsGetValue)(DWORD)
 
static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION
 
static VOID init_funcs (void)
 
static VOID WINAPI FiberLocalStorageProc (PVOID lpFlsData)
 
static VOID WINAPI FiberMainProc (LPVOID lpFiberParameter)
 
static void test_ConvertThreadToFiber (void)
 
static void test_ConvertThreadToFiberEx (void)
 
static void test_ConvertFiberToThread (void)
 
static void test_FiberHandling (void)
 
static unsigned int check_linked_list (const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
 
static void WINAPI test_fls_callback (void *data)
 
static unsigned int test_fls_chunk_size (unsigned int chunk_index)
 
static unsigned int test_fls_chunk_index_from_index (unsigned int index, unsigned int *index_in_chunk)
 
static DWORD WINAPI test_FiberLocalStorage_thread (void *arg)
 
static void test_FiberLocalStorage (void)
 
static void test_FiberLocalStorageCallback (PFLS_CALLBACK_FUNCTION cbfunc)
 
static void test_FiberLocalStorageWithFibers (PFLS_CALLBACK_FUNCTION cbfunc)
 
static void check_current_actctx_is_ (int line, HANDLE expected_actctx, BOOL todo)
 
static DWORD WINAPI subthread_actctx_func (void *actctx)
 
static void WINAPI fiber_actctx_func (void *actctx)
 
static void subtest_fiber_actctx_switch (HANDLE current_actctx, HANDLE child_actctx)
 
static void WINAPI exit_thread_fiber_func (void *unused)
 
static DWORD WINAPI thread_actctx_func_early_exit (void *actctx)
 
static void subtest_fiber_actctx_preservation (HANDLE current_actctx, HANDLE child_actctx)
 
static HANDLE create_actctx_from_module_manifest (void)
 
static void test_fiber_actctx (void)
 
static void WINAPI fls_exit_deadlock_callback (void *arg)
 
static DWORD CALLBACK fls_exit_deadlock_thread (void *arg)
 
static void fls_exit_deadlock_child (void)
 
static void test_fls_exit_deadlock (void)
 
 START_TEST (fiber)
 

Variables

static LPFIBER_START_ROUTINE
 
static LPVOID
 
static DWORD
 
static SIZE_T
 
static PVOID
 
static void *static void **static ULONG flags
 
static voidfibers [3]
 
static BYTE testparam = 185
 
static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES
 
static voidfls_value_to_set
 
static int fiberCount = 0
 
static int cbCount = 0
 
static unsigned int test_fls_callback_call_count
 
static HANDLE test_fiberlocalstorage_peb_locked_event
 
static HANDLE test_fiberlocalstorage_done_event
 

Macro Definition Documentation

◆ check_current_actctx_is

#define check_current_actctx_is (   e,
  t 
)    check_current_actctx_is_(__LINE__, e, t)

Definition at line 805 of file fiber.c.

◆ FLS_TEST_INDEX_COUNT

#define FLS_TEST_INDEX_COUNT   4096

Definition at line 220 of file fiber.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 24 of file fiber.c.

◆ X [1/2]

#define X (   f)    p##f = (void*)GetProcAddress(hKernel32, #f);

◆ X [2/2]

#define X (   f)    p##f = (void*)GetProcAddress(hntdll, #f);

Function Documentation

◆ BOOL()

static BOOL ( WINAPI pConvertFiberToThread)
static

◆ check_current_actctx_is_()

static void check_current_actctx_is_ ( int  line,
HANDLE  expected_actctx,
BOOL  todo 
)
static

Definition at line 806 of file fiber.c.

807{
808 HANDLE cur_actctx;
809 BOOL ret;
810
811 cur_actctx = (void*)0xdeadbeef;
812 ret = GetCurrentActCtx(&cur_actctx);
813 ok_(__FILE__, line)(ret, "thread GetCurrentActCtx failed, %lu\n", GetLastError());
814
816 ok_(__FILE__, line)(cur_actctx == expected_actctx, "got %p, expected %p\n", cur_actctx, expected_actctx);
817
818 ReleaseActCtx(cur_actctx);
819}
#define ok_(x1, x2)
Definition: atltest.h:61
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
Definition: actctx.c:208
BOOL WINAPI GetCurrentActCtx(OUT PHANDLE phActCtx)
Definition: actctx.c:298
return ret
Definition: mutex.c:146
unsigned int BOOL
Definition: ntddk_ex.h:94
#define todo_wine_if(is_todo)
Definition: minitest.h:81
BOOL todo
Definition: filedlg.c:313
Definition: parser.c:49
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

◆ check_linked_list()

static unsigned int check_linked_list ( const LIST_ENTRY le,
const LIST_ENTRY search_entry,
unsigned int index_found 
)
static

Definition at line 222 of file fiber.c.

223{
224 unsigned int count = 0;
226
227 *index_found = ~0;
228
229 for (entry = le->Flink; entry != le; entry = entry->Flink)
230 {
231 if (entry == search_entry)
232 {
233 ok(*index_found == ~0, "Duplicate list entry.\n");
234 *index_found = count;
235 }
236 ++count;
237 }
238 return count;
239}
#define ok(value,...)
Definition: atltest.h:57
GLuint GLuint GLsizei count
Definition: gl.h:1545
uint32_t entry
Definition: isohybrid.c:63
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121

Referenced by test_FiberLocalStorage().

◆ create_actctx_from_module_manifest()

static HANDLE create_actctx_from_module_manifest ( void  )
static

Definition at line 966 of file fiber.c.

967{
968 ACTCTXW actctx;
969
970 memset(&actctx, 0, sizeof(ACTCTXW));
971 actctx.cbSize = sizeof(actctx);
972 actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
973 actctx.lpResourceName = MAKEINTRESOURCEW(124);
974 actctx.hModule = GetModuleHandleW(NULL);
975
976 return CreateActCtxW(&actctx);
977}
#define NULL
Definition: types.h:112
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
Definition: actctx.c:102
#define actctx
Definition: kernel32.h:8
#define memset(x, y, z)
Definition: compat.h:39
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582

Referenced by test_fiber_actctx().

◆ DWORD()

static DWORD ( WINAPI pFlsAlloc)
static

◆ exit_thread_fiber_func()

static void WINAPI exit_thread_fiber_func ( void unused)
static

Definition at line 898 of file fiber.c.

899{
900 BOOL ret;
901
902 ret = pConvertFiberToThread();
903 ok(ret, "ConvertFiberToThread returned error %lu\n", GetLastError());
904
905 ExitThread(16);
906}
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365

Referenced by thread_actctx_func_early_exit().

◆ fiber_actctx_func()

static void WINAPI fiber_actctx_func ( void actctx)
static

Definition at line 845 of file fiber.c.

846{
848 DWORD tid, wait;
850 BOOL ret;
851
853
855 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
857
860
862 ok(thread != NULL, "CreateThread returned error %lu\n", GetLastError());
863
865 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (last error: %lu)\n",
866 wait, GetLastError());
868
870 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
872
874 ok(0, "unreachable\n");
875}
static HANDLE thread
Definition: service.c:33
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
Definition: actctx.c:268
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
Definition: actctx.c:237
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
void WINAPI DECLSPEC_HOTPATCH SwitchToFiber(LPVOID fiber)
Definition: thread.c:1172
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
static TfClientId tid
static void * fibers[3]
Definition: fiber.c:48
#define check_current_actctx_is(e, t)
Definition: fiber.c:805
static DWORD WINAPI subthread_actctx_func(void *actctx)
Definition: fiber.c:821
Definition: cookie.c:34
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define WAIT_OBJECT_0
Definition: winbase.h:383

Referenced by subtest_fiber_actctx_switch().

◆ FiberLocalStorageProc()

static VOID WINAPI FiberLocalStorageProc ( PVOID  lpFlsData)
static

Definition at line 88 of file fiber.c.

89{
90 ok(lpFlsData == fls_value_to_set,
91 "FlsData expected not to be changed, value is %p, expected %p\n",
92 lpFlsData, fls_value_to_set);
93 cbCount++;
94}
static int cbCount
Definition: fiber.c:54
static void * fls_value_to_set
Definition: fiber.c:51

Referenced by START_TEST().

◆ FiberMainProc()

static VOID WINAPI FiberMainProc ( LPVOID  lpFiberParameter)
static

Definition at line 96 of file fiber.c.

97{
98 BYTE *tparam = (BYTE *)lpFiberParameter;
99 TEB *teb = NtCurrentTeb();
100
101 ok(!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots);
102
103 fiberCount++;
104 ok(*tparam == 185, "Parameterdata expected not to be changed\n");
106 {
107 void* ret;
108 BOOL bret;
109
110 SetLastError( 0xdeadbeef );
111 ret = pFlsGetValue(fls_index_to_set);
112 ok(ret == NULL, "FlsGetValue returned %p, expected NULL\n", ret);
113 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %lu.\n", GetLastError());
114
115 /* Set the FLS value */
116 bret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
117 ok(bret, "FlsSetValue failed with error %lu\n", GetLastError());
118
119 ok(!!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots);
120
121 /* Verify that FlsGetValue retrieves the value set by FlsSetValue */
122 SetLastError( 0xdeadbeef );
123 ret = pFlsGetValue(fls_index_to_set);
124 ok(ret == fls_value_to_set, "FlsGetValue returned %p, expected %p\n", ret, fls_value_to_set);
125 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue error %lu\n", GetLastError());
126 }
127 pSwitchToFiber(fibers[0]);
128}
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define NtCurrentTeb
static DWORD fls_index_to_set
Definition: fiber.c:50
static int fiberCount
Definition: fiber.c:53
Definition: compat.h:836
TEB_FLS_DATA * FlsSlots
Definition: winternl.h:690
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:556
unsigned char BYTE
Definition: xxhash.c:193

Referenced by test_FiberHandling(), and test_FiberLocalStorageWithFibers().

◆ fls_exit_deadlock_callback()

static void WINAPI fls_exit_deadlock_callback ( void arg)
static

Definition at line 1034 of file fiber.c.

1035{
1036 if (arg == (void *)1)
1037 Sleep(INFINITE);
1038 if (arg == (void *)2)
1039 /* Unfortunately this test won't affect the exit code if it fails, but
1040 * at least it will print a failure message. */
1041 ok(RtlDllShutdownInProgress(), "expected DLL shutdown\n");
1042}
NTSYSAPI BOOLEAN WINAPI RtlDllShutdownInProgress(void)
Definition: ldrapi.c:1559
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790

Referenced by fls_exit_deadlock_child().

◆ fls_exit_deadlock_child()

static void fls_exit_deadlock_child ( void  )
static

Definition at line 1050 of file fiber.c.

1051{
1053 FlsSetValue(index, (void *)2);
1055 Sleep(100);
1056 ExitProcess(0);
1057}
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
GLuint index
Definition: glext.h:6031
static DWORD CALLBACK fls_exit_deadlock_thread(void *arg)
Definition: fiber.c:1044
static void WINAPI fls_exit_deadlock_callback(void *arg)
Definition: fiber.c:1034
uint32_t DWORD_PTR
Definition: typedefs.h:65

Referenced by START_TEST().

◆ fls_exit_deadlock_thread()

static DWORD CALLBACK fls_exit_deadlock_thread ( void arg)
static

Definition at line 1044 of file fiber.c.

1045{
1046 FlsSetValue((DWORD_PTR)arg, (void *)1);
1047 return 0;
1048}

Referenced by fls_exit_deadlock_child().

◆ init_funcs()

static VOID init_funcs ( void  )
static

Definition at line 56 of file fiber.c.

57{
58 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
59 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
60
61#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
70 X(FlsAlloc);
71 X(FlsFree);
74#undef X
75
76#define X(f) p##f = (void*)GetProcAddress(hntdll, #f);
84#undef X
85
86}
LPVOID WINAPI ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter, _In_ DWORD dwFlags)
Definition: fiber.c:99
LPVOID WINAPI CreateFiberEx(_In_ SIZE_T dwStackCommitSize, _In_ SIZE_T dwStackReserveSize, _In_ DWORD dwFlags, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:191
VOID WINAPI DeleteFiber(_In_ LPVOID lpFiber)
Definition: fiber.c:290
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
LPVOID WINAPI ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
Definition: fiber.c:162
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
LPVOID WINAPI CreateFiber(_In_ SIZE_T dwStackSize, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:174
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
BOOL WINAPI DECLSPEC_HOTPATCH ConvertFiberToThread(void)
Definition: thread.c:1084
BOOL WINAPI DECLSPEC_HOTPATCH IsThreadAFiber(void)
Definition: thread.c:1163
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:84
NTSYSAPI NTSTATUS WINAPI RtlFlsSetValue(ULONG, void *)
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:74
NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION, ULONG *)
NTSYSAPI NTSTATUS WINAPI RtlFlsFree(ULONG)
NTSYSAPI NTSTATUS WINAPI RtlFlsGetValue(ULONG, void **)
NTSYSAPI void WINAPI RtlProcessFlsData(void *, ULONG)
HANDLE hKernel32
Definition: locale.c:13
#define X(f)
static HINSTANCE hntdll
Definition: process.c:68

Referenced by START_TEST().

◆ LPVOID()

static LPVOID ( WINAPI pCreateFiber)
static

◆ NTSTATUS()

static NTSTATUS ( WINAPI pRtlFlsAlloc)
static

◆ PVOID()

static PVOID ( WINAPI pFlsGetValue)
static

◆ START_TEST()

START_TEST ( fiber  )

Definition at line 1091 of file fiber.c.

1092{
1093 char **argv;
1094 int argc;
1095
1097
1098 if (argc == 3 && !strcmp(argv[2], "fls_exit_deadlock"))
1099 {
1101 return;
1102 }
1103
1104 init_funcs();
1105
1106 if (!pCreateFiber)
1107 {
1108 win_skip( "Fibers not supported by win95\n" );
1109 return;
1110 }
1111
1118}
static int argc
Definition: ServiceArgs.c:12
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
#define win_skip
Definition: minitest.h:67
static void test_fiber_actctx(void)
Definition: fiber.c:979
static void fls_exit_deadlock_child(void)
Definition: fiber.c:1050
static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:736
static VOID init_funcs(void)
Definition: fiber.c:56
static void test_FiberHandling(void)
Definition: fiber.c:183
static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:694
static void test_FiberLocalStorage(void)
Definition: fiber.c:277
static void test_fls_exit_deadlock(void)
Definition: fiber.c:1059
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
Definition: fiber.c:88
#define argv
Definition: mplay32.c:18
int winetest_get_mainargs(char ***pargv)

◆ subtest_fiber_actctx_preservation()

static void subtest_fiber_actctx_preservation ( HANDLE  current_actctx,
HANDLE  child_actctx 
)
static

Definition at line 931 of file fiber.c.

932{
934 DWORD tid, wait;
936 BOOL ret;
937
938 ret = ActivateActCtx(child_actctx, &cookie);
939 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
940 check_current_actctx_is(child_actctx, FALSE);
941
942 thread = CreateThread(NULL, 0, thread_actctx_func_early_exit, child_actctx, 0, &tid);
943 ok(thread != NULL, "CreateThread returned error %lu\n", GetLastError());
944
946 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
947 check_current_actctx_is(current_actctx, FALSE);
948
950 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (last error: %lu)\n",
951 wait, GetLastError());
953
954 /* The exited thread has been converted to a fiber */
955#if defined(__REACTOS__) && defined(_M_AMD64)
956 skip("FIXME: SwitchToFiber() is unimplemented on AMD64 ReactOS\n");
957#else
959 check_current_actctx_is(current_actctx, FALSE);
960
962 fibers[1] = NULL;
963#endif
964}
#define skip(...)
Definition: atltest.h:64
static DWORD WINAPI thread_actctx_func_early_exit(void *actctx)
Definition: fiber.c:908

Referenced by test_fiber_actctx().

◆ subtest_fiber_actctx_switch()

static void subtest_fiber_actctx_switch ( HANDLE  current_actctx,
HANDLE  child_actctx 
)
static

Definition at line 878 of file fiber.c.

879{
880 fibers[1] = pCreateFiber(0, fiber_actctx_func, child_actctx);
881 ok(fibers[1] != NULL, "CreateFiber returned error %lu\n", GetLastError());
882 check_current_actctx_is(current_actctx, FALSE);
883
885 check_current_actctx_is(current_actctx, FALSE);
886
888 check_current_actctx_is(current_actctx, FALSE);
889
891 check_current_actctx_is(current_actctx, FALSE);
892 ok(fibers[2] == NULL, "expected fiber to be deleted (got %p)\n", fibers[2]);
893
895 fibers[1] = NULL;
896}
static void WINAPI fiber_actctx_func(void *actctx)
Definition: fiber.c:845

Referenced by test_fiber_actctx().

◆ subthread_actctx_func()

static DWORD WINAPI subthread_actctx_func ( void actctx)
static

Definition at line 821 of file fiber.c.

822{
823 HANDLE fiber;
824 BOOL ret;
825
827
828 fiber = pConvertThreadToFiber(NULL);
829 ok(fiber != NULL, "ConvertThreadToFiber returned error %lu\n", GetLastError());
831 fibers[2] = fiber;
832
835
836 ok(fibers[2] == fiber, "fibers[2]: expected %p, got %p\n", fiber, fibers[2]);
837 fibers[2] = NULL;
838 ret = pConvertFiberToThread();
839 ok(ret, "ConvertFiberToThread returned error %lu\n", GetLastError());
841
842 return 0;
843}

Referenced by fiber_actctx_func().

◆ test_ConvertFiberToThread()

static void test_ConvertFiberToThread ( void  )
static

Definition at line 170 of file fiber.c.

171{
172 if (pConvertFiberToThread)
173 {
174 BOOL ret = pConvertFiberToThread();
175 ok(ret, "ConvertFiberToThread failed with error %lu\n", GetLastError());
176 }
177 else
178 {
179 win_skip( "ConvertFiberToThread not present\n" );
180 }
181}

Referenced by test_fiber_actctx(), test_FiberHandling(), and test_FiberLocalStorageWithFibers().

◆ test_ConvertThreadToFiber()

static void test_ConvertThreadToFiber ( void  )
static

Definition at line 130 of file fiber.c.

131{
132 void *ret;
133
134 if (pConvertThreadToFiber)
135 {
136 fibers[0] = pConvertThreadToFiber(&testparam);
137 ok(fibers[0] != NULL, "ConvertThreadToFiber failed with error %lu\n", GetLastError());
138
139 SetLastError(0xdeadbeef);
140 ret = pConvertThreadToFiber(&testparam);
141 ok(!ret, "Got non NULL ret.\n");
142 ok(GetLastError() == ERROR_ALREADY_FIBER, "Got unexpected error %lu.\n", GetLastError());
143 }
144 else
145 {
146 win_skip( "ConvertThreadToFiber not present\n" );
147 }
148}
static BYTE testparam
Definition: fiber.c:49
#define ERROR_ALREADY_FIBER
Definition: winerror.h:1107

Referenced by test_fiber_actctx(), test_FiberHandling(), and test_FiberLocalStorageWithFibers().

◆ test_ConvertThreadToFiberEx()

static void test_ConvertThreadToFiberEx ( void  )
static

Definition at line 150 of file fiber.c.

151{
152 void *ret;
153
154 if (pConvertThreadToFiberEx)
155 {
156 fibers[0] = pConvertThreadToFiberEx(&testparam, 0);
157 ok(fibers[0] != NULL, "ConvertThreadToFiberEx failed with error %lu\n", GetLastError());
158
159 SetLastError(0xdeadbeef);
160 ret = pConvertThreadToFiberEx(&testparam, 0);
161 ok(!ret, "Got non NULL ret.\n");
162 ok(GetLastError() == ERROR_ALREADY_FIBER, "Got unexpected error %lu.\n", GetLastError());
163 }
164 else
165 {
166 win_skip( "ConvertThreadToFiberEx not present\n" );
167 }
168}

Referenced by test_FiberHandling().

◆ test_fiber_actctx()

static void test_fiber_actctx ( void  )
static

Definition at line 979 of file fiber.c.

980{
982 HANDLE actctxs[3];
983 size_t i, j;
984 BOOL ret;
985
986#ifdef __REACTOS__
988 skip("test_fiber_actctx() crashes and isn't valid on WS03.\n");
989 return;
990 }
991#endif
992 for (i = 0; i < ARRAY_SIZE(actctxs); i++)
993 {
995 ok(actctxs[i] != INVALID_HANDLE_VALUE, "failed to create context, error %lu\n", GetLastError());
996 for (j = 0; j < i; j++)
997 {
998 ok(actctxs[i] != actctxs[j],
999 "actctxs[%Iu] (%p) and actctxs[%Iu] (%p) should not alias\n",
1000 i, actctxs[i], j, actctxs[j]);
1001 }
1002 }
1003
1004 ret = ActivateActCtx(actctxs[0], &cookies[0]);
1005 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
1006 check_current_actctx_is(actctxs[0], FALSE);
1007
1009 check_current_actctx_is(actctxs[0], FALSE);
1010
1011 ret = ActivateActCtx(actctxs[1], &cookies[1]);
1012 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
1013 check_current_actctx_is(actctxs[1], FALSE);
1014
1015 subtest_fiber_actctx_switch(actctxs[1], actctxs[2]);
1016 subtest_fiber_actctx_preservation(actctxs[1], actctxs[2]);
1017
1018 ret = DeactivateActCtx(0, cookies[1]);
1019 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
1020 check_current_actctx_is(actctxs[0], FALSE);
1021
1023 check_current_actctx_is(actctxs[0], FALSE);
1024
1025 ret = DeactivateActCtx(0, cookies[0]);
1026 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
1028
1029 for (i = ARRAY_SIZE(actctxs); i > 0; )
1030 ReleaseActCtx(actctxs[--i]);
1031}
#define GetNTVersion()
Definition: apitest.h:17
#define ARRAY_SIZE(A)
Definition: main.h:20
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static HANDLE create_actctx_from_module_manifest(void)
Definition: fiber.c:966
static void test_ConvertFiberToThread(void)
Definition: fiber.c:170
static void test_ConvertThreadToFiber(void)
Definition: fiber.c:130
static void subtest_fiber_actctx_preservation(HANDLE current_actctx, HANDLE child_actctx)
Definition: fiber.c:931
static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actctx)
Definition: fiber.c:878
static CookieInternal * cookies
Definition: msctf.cpp:37
#define is_reactos()
Definition: test.h:1041
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25

Referenced by START_TEST().

◆ test_FiberHandling()

static void test_FiberHandling ( void  )
static

Definition at line 183 of file fiber.c.

184{
185 fiberCount = 0;
186 fibers[0] = pCreateFiber(0,FiberMainProc,&testparam);
187 ok(fibers[0] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
188 pDeleteFiber(fibers[0]);
189
192 if (pConvertThreadToFiberEx)
194 else
196
197 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
198 ok(fibers[1] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
199
200 pSwitchToFiber(fibers[1]);
201 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
202 pDeleteFiber(fibers[1]);
203
204 if (pCreateFiberEx)
205 {
206 fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam);
207 ok(fibers[1] != NULL, "CreateFiberEx failed with error %lu\n", GetLastError());
208
209 pSwitchToFiber(fibers[1]);
210 ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount);
211 pDeleteFiber(fibers[1]);
212 }
213 else win_skip( "CreateFiberEx not present\n" );
214
215 if (pIsThreadAFiber) ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n");
217 if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
218}
static void test_ConvertThreadToFiberEx(void)
Definition: fiber.c:150
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
Definition: fiber.c:96

Referenced by START_TEST().

◆ test_FiberLocalStorage()

static void test_FiberLocalStorage ( void  )
static

Definition at line 277 of file fiber.c.

278{
279 static DWORD fls_indices[FLS_TEST_INDEX_COUNT];
280 unsigned int i, j, count, entry_count, index;
281 LIST_ENTRY *fls_list_head, saved_entry;
282 TEB_FLS_DATA *fls_data, *new_fls_data;
283 GLOBAL_FLS_DATA *g_fls_data;
284 DWORD fls, fls_2, result;
285 TEB *teb = NtCurrentTeb();
286 PEB *peb = teb->Peb;
288 HANDLE hthread;
289 ULONG index2;
290 SIZE_T size;
291 void* val;
292 BOOL ret;
293
294 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
295 {
296 win_skip( "Fiber Local Storage not supported\n" );
297 return;
298 }
299
300 if (pRtlFlsAlloc)
301 {
302 if (pRtlFlsGetValue)
303 {
304 status = pRtlFlsGetValue(0, NULL);
305 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
306 }
307 else
308 {
309 win_skip("RtlFlsGetValue is not available.\n");
310 }
311
312 for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i)
313 {
314 fls_indices[i] = 0xdeadbeef;
315 status = pRtlFlsAlloc(test_fls_callback, &fls_indices[i]);
316 ok(!status || status == STATUS_NO_MEMORY, "Got unexpected status %#lx.\n", status);
317 if (status)
318 {
319 ok(fls_indices[i] == 0xdeadbeef, "Got unexpected index %#lx.\n", fls_indices[i]);
320 break;
321 }
322 if (pRtlFlsSetValue)
323 {
324 status = pRtlFlsSetValue(fls_indices[i], (void *)(ULONG_PTR)(i + 1));
325 ok(!status, "Got unexpected status %#lx.\n", status);
326 }
327 }
328 count = i;
329
330 fls_data = teb->FlsSlots;
331
332 /* FLS limits are increased since Win10 18312. */
333 ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count);
334
335#if defined(__REACTOS__) && defined(_WIN64)
336 /* peb layout is different on ReactOS x64 */
337 if (!is_reactos() && !peb->FlsCallback)
338#else
339 if (!peb->FlsCallback)
340#endif
341 {
342 ok(pRtlFlsSetValue && pRtlFlsGetValue, "Missing RtlFlsGetValue / RtlFlsSetValue.\n");
343 ok(!peb->FlsBitmap, "Got unexpected FlsBitmap %p.\n", peb->FlsBitmap);
344 ok(!peb->FlsListHead.Flink && !peb->FlsListHead.Blink, "Got nonzero FlsListHead.\n");
345 ok(!peb->FlsHighIndex, "Got unexpected FlsHighIndex %lu.\n", peb->FlsHighIndex);
346
348
349 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
350 ok(entry_count == 1, "Got unexpected count %u.\n", entry_count);
351 ok(!index, "Got unexpected index %u.\n", index);
352
354
355 ok(g_fls_data->fls_high_index == 0xfef, "Got unexpected fls_high_index %#lx.\n", g_fls_data->fls_high_index);
356
357 for (i = 0; i < 8; ++i)
358 {
359 ok(!!g_fls_data->fls_callback_chunks[i], "Got zero fls_callback_chunks[%u].\n", i);
361 "Got unexpected g_fls_data->fls_callback_chunks[%u]->count %lu.\n",
362 i, g_fls_data->fls_callback_chunks[i]->count);
363
364 size = HeapSize(GetProcessHeap(), 0, g_fls_data->fls_callback_chunks[i]);
365 ok(size == sizeof(ULONG_PTR) + sizeof(FLS_CALLBACK) * test_fls_chunk_size(i),
366 "Got unexpected size %p.\n", (void *)size);
367
368 ok(!!fls_data->fls_data_chunks[i], "Got zero fls_data->fls_data_chunks[%u].\n", i);
369 ok(!fls_data->fls_data_chunks[i][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
370 i, fls_data->fls_data_chunks[i][0]);
371 size = HeapSize(GetProcessHeap(), 0, fls_data->fls_data_chunks[i]);
372 ok(size == sizeof(void *) * (test_fls_chunk_size(i) + 1), "Got unexpected size %p.\n", (void *)size);
373
374 if (!i)
375 {
376 ok(g_fls_data->fls_callback_chunks[0]->callbacks[0].callback == (void *)~(ULONG_PTR)0,
377 "Got unexpected callback %p.\n",
378 g_fls_data->fls_callback_chunks[0]->callbacks[0].callback);
379 }
380
381 for (j = i ? 0 : fls_indices[0]; j < test_fls_chunk_size(i); ++j)
382 {
383 ok(!g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown,
384 "Got unexpected unknown %p, i %u, j %u.\n",
385 g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown, i, j);
387 "Got unexpected callback %p, i %u, j %u.\n",
388 g_fls_data->fls_callback_chunks[i]->callbacks[j].callback, i, j);
389 }
390 }
391 for (i = 0; i < count; ++i)
392 {
393 j = test_fls_chunk_index_from_index(fls_indices[i], &index);
394 ok(fls_data->fls_data_chunks[j][index + 1] == (void *)(ULONG_PTR)(i + 1),
395 "Got unexpected FLS value %p, i %u, j %u, index %u.\n",
396 fls_data->fls_data_chunks[j][index + 1], i, j, index);
397 }
398 j = test_fls_chunk_index_from_index(fls_indices[0x10], &index);
400 status = pRtlFlsFree(fls_indices[0x10]);
401 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
402
405 status = pRtlFlsFree(fls_indices[0x10]);
406 ok(!status, "Got unexpected status %#lx.\n", status);
407 ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
409
410 ok(!fls_data->fls_data_chunks[j][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
411 j, fls_data->fls_data_chunks[j][0]);
413 "Got unexpected callback %p.\n",
415
416 fls_data->fls_data_chunks[j][index + 1] = (void *)(ULONG_PTR)0x28;
417 status = pRtlFlsAlloc(test_fls_callback, &index2);
418 ok(!status, "Got unexpected status %#lx.\n", status);
419 ok(index2 == fls_indices[0x10], "Got unexpected index %lu.\n", index2);
420 ok(fls_data->fls_data_chunks[j][index + 1] == (void *)(ULONG_PTR)0x28, "Got unexpected data %p.\n",
421 fls_data->fls_data_chunks[j][index + 1]);
422
423 status = pRtlFlsSetValue(index2, (void *)(ULONG_PTR)0x11);
424 ok(!status, "Got unexpected status %#lx.\n", status);
425
426 teb->FlsSlots = NULL;
427
428 val = (void *)0xdeadbeef;
429 status = pRtlFlsGetValue(fls_indices[1], &val);
430 new_fls_data = teb->FlsSlots;
431 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
432 ok(val == (void *)0xdeadbeef, "Got unexpected val %p.\n", val);
433 ok(!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
434
435 status = pRtlFlsSetValue(fls_indices[1], (void *)(ULONG_PTR)0x28);
436 new_fls_data = teb->FlsSlots;
437 ok(!status, "Got unexpected status %#lx.\n", status);
438 ok(!!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
439
440 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
441 ok(entry_count == 2, "Got unexpected count %u.\n", entry_count);
442 ok(!index, "Got unexpected index %u.\n", index);
444 ok(index == 1, "Got unexpected index %u.\n", index);
445
446 val = (void *)0xdeadbeef;
447 status = pRtlFlsGetValue(fls_indices[2], &val);
448 ok(!status, "Got unexpected status %#lx.\n", status);
449 ok(!val, "Got unexpected val %p.\n", val);
450
451
452 /* With bit 0 of flags set RtlProcessFlsData is removing FLS data from the linked list
453 * and calls FLS callbacks. With bit 1 set the memory is freed. The remaining bits do not seem
454 * to have any obvious effect. */
455 for (i = 2; i < 32; ++i)
456 {
457 pRtlProcessFlsData(new_fls_data, 1 << i);
458 size = HeapSize(GetProcessHeap(), 0, new_fls_data);
459 ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size);
460 }
461
462 if (0)
463 {
464 pRtlProcessFlsData(new_fls_data, 2);
465 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
466 ok(entry_count == 2, "Got unexpected count %u.\n", entry_count);
467
468 /* Crashes on Windows. */
469 HeapSize(GetProcessHeap(), 0, new_fls_data);
470 }
471
475 ok(!!hthread, "CreateThread failed.\n");
477 ok(result == WAIT_OBJECT_0, "Got unexpected result %lu.\n", result);
478 teb->FlsSlots = NULL;
479
481 saved_entry = new_fls_data->fls_list_entry;
482 pRtlProcessFlsData(new_fls_data, 1);
483 ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots);
484
485 teb->FlsSlots = fls_data;
486 ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
488
491 CloseHandle(hthread);
494
495 ok(new_fls_data->fls_list_entry.Flink == saved_entry.Flink, "Got unexpected Flink %p.\n",
496 saved_entry.Flink);
497 ok(new_fls_data->fls_list_entry.Blink == saved_entry.Blink, "Got unexpected Flink %p.\n",
498 saved_entry.Blink);
499 size = HeapSize(GetProcessHeap(), 0, new_fls_data);
500 ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size);
502 i = test_fls_chunk_index_from_index(fls_indices[1], &index);
503 new_fls_data->fls_data_chunks[i][index + 1] = (void *)(ULONG_PTR)0x28;
504 pRtlProcessFlsData(new_fls_data, 2);
505 ok(!test_fls_callback_call_count, "Got unexpected callback call count %u.\n",
507
508 if (0)
509 {
510 /* crashes on Windows. */
511 HeapSize(GetProcessHeap(), 0, new_fls_data);
512 }
513
514 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
515 ok(entry_count == 1, "Got unexpected count %u.\n", entry_count);
516 ok(!index, "Got unexpected index %u.\n", index);
517 }
518 else
519 {
520 win_skip("Old FLS data storage layout, skipping test.\n");
521 g_fls_data = NULL;
522 }
523
524 if (0)
525 {
526 /* crashes on Windows. */
527 pRtlFlsGetValue(fls_indices[0], NULL);
528 }
529
530 for (i = 0; i < count; ++i)
531 {
532 if (pRtlFlsGetValue)
533 {
534 status = pRtlFlsGetValue(fls_indices[i], &val);
535 ok(!status, "Got unexpected status %#lx.\n", status);
536 ok(val == (void *)(ULONG_PTR)(i + 1), "Got unexpected val %p, i %u.\n", val, i);
537 }
538
539 status = pRtlFlsFree(fls_indices[i]);
540 ok(!status, "Got unexpected status %#lx, i %u.\n", status, i);
541 }
542
543#if defined(__REACTOS__) && defined(_WIN64)
544 /* peb layout is different on ReactOS x64 */
545 if (!is_reactos() && !peb->FlsCallback)
546#else
547 if (!peb->FlsCallback)
548#endif
549 {
550 ok(g_fls_data->fls_high_index == 0xfef, "Got unexpected fls_high_index %#lx.\n",
551 g_fls_data->fls_high_index);
552
553 for (i = 0; i < 8; ++i)
554 {
555 ok(!!g_fls_data->fls_callback_chunks[i], "Got zero fls_callback_chunks[%u].\n", i);
556 ok(!!fls_data->fls_data_chunks[i], "Got zero fls_data->fls_data_chunks[%u].\n", i);
557 }
558 }
559 }
560 else
561 {
562 win_skip("RtlFlsAlloc is not available.\n");
563 }
564
565 /* Test an unallocated index
566 * FlsFree should fail
567 * FlsGetValue and FlsSetValue should succeed
568 */
569 SetLastError( 0xdeadbeef );
570 ret = pFlsFree( 127 );
571 ok( !ret, "freeing fls index 127 (unallocated) succeeded\n" );
573 "freeing fls index 127 (unallocated) wrong error %lu\n", GetLastError() );
574
575 val = pFlsGetValue( 127 );
576 ok( val == NULL,
577 "getting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
578
579 if (pRtlFlsGetValue)
580 {
581 val = (void *)0xdeadbeef;
582 status = pRtlFlsGetValue(127, &val);
583 ok( !status, "Got unexpected status %#lx.\n", status );
584 ok( !val, "Got unexpected val %p.\n", val );
585 }
586
587 ret = pFlsSetValue( 127, (void*) 0x217 );
588 ok( ret, "setting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
589
590 SetLastError( 0xdeadbeef );
591 val = pFlsGetValue( 127 );
592 ok( val == (void*) 0x217, "fls index 127 (unallocated) wrong value %p\n", val );
594 "getting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
595
596 if (pRtlFlsGetValue)
597 {
598 val = (void *)0xdeadbeef;
599 status = pRtlFlsGetValue(127, &val);
600 ok( !status, "Got unexpected status %#lx.\n", status );
601 ok( val == (void*)0x217, "Got unexpected val %p.\n", val );
602 }
603
604 /* FlsFree, FlsGetValue, and FlsSetValue out of bounds should return
605 * ERROR_INVALID_PARAMETER
606 */
607 SetLastError( 0xdeadbeef );
608 ret = pFlsFree( 128 );
609 ok( !ret, "freeing fls index 128 (out of bounds) succeeded\n" );
611 "freeing fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
612
613 SetLastError( 0xdeadbeef );
614 ret = pFlsSetValue( 128, (void*) 0x217 );
616 "setting fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
617
618 SetLastError( 0xdeadbeef );
619 val = pFlsGetValue( 128 );
620 ok( GetLastError() == ERROR_INVALID_PARAMETER || val == (void *)0x217,
621 "getting fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
622
623 /* Test index 0 */
624 SetLastError( 0xdeadbeef );
625 val = pFlsGetValue( 0 );
626 ok( !val, "fls index 0 set to %p\n", val );
627 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
628 if (pRtlFlsGetValue)
629 {
630 val = (void *)0xdeadbeef;
631 status = pRtlFlsGetValue(0, &val);
632 ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status );
633 ok( val == (void*)0xdeadbeef, "Got unexpected val %p.\n", val );
634 }
635
636 SetLastError( 0xdeadbeef );
637 ret = pFlsSetValue( 0, (void *)0xdeadbeef );
638 ok( !ret, "setting fls index 0 succeeded\n" );
639 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
640 if (pRtlFlsSetValue)
641 {
642 status = pRtlFlsSetValue( 0, (void *)0xdeadbeef );
643 ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status );
644 }
645 SetLastError( 0xdeadbeef );
646 val = pFlsGetValue( 0 );
647 ok( !val, "fls index 0 wrong value %p\n", val );
648 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
649
650 /* Test creating an FLS index */
651 fls = pFlsAlloc( NULL );
652 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
653 ok( fls != 0, "fls index 0 allocated\n" );
654 val = pFlsGetValue( fls );
655 ok( !val, "fls index %lu wrong value %p\n", fls, val );
656 SetLastError( 0xdeadbeef );
657 ret = pFlsSetValue( fls, (void *)0xdeadbeef );
658 ok( ret, "setting fls index %lu failed\n", fls );
659 ok( GetLastError() == 0xdeadbeef, "setting fls index wrong error %lu\n", GetLastError() );
660 SetLastError( 0xdeadbeef );
661 val = pFlsGetValue( fls );
662 ok( val == (void *)0xdeadbeef, "fls index %lu wrong value %p\n", fls, val );
664 "getting fls index %lu failed with error %lu\n", fls, GetLastError() );
665 pFlsFree( fls );
666
667 /* Undefined behavior: verify the value is NULL after it the slot is freed */
668 SetLastError( 0xdeadbeef );
669 val = pFlsGetValue( fls );
670 ok( val == NULL, "fls index %lu wrong value %p\n", fls, val );
672 "getting fls index %lu failed with error %lu\n", fls, GetLastError() );
673
674 /* Undefined behavior: verify the value is settable after the slot is freed */
675 ret = pFlsSetValue( fls, (void *)0xdeadbabe );
676 ok( ret, "setting fls index %lu failed\n", fls );
677 val = pFlsGetValue( fls );
678 ok( val == (void *)0xdeadbabe, "fls index %lu wrong value %p\n", fls, val );
679
680 /* Try to create the same FLS index again, and verify that is initialized to NULL */
681 fls_2 = pFlsAlloc( NULL );
682 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
683 /* If this fails it is not an API error, but the test will be inconclusive */
684 ok( fls_2 == fls, "different FLS index allocated, was %lu, now %lu\n", fls, fls_2 );
685
686 SetLastError( 0xdeadbeef );
687 val = pFlsGetValue( fls_2 );
688 ok( val == NULL || val == (void *)0xdeadbabe, "fls index %lu wrong value %p\n", fls, val );
690 "getting fls index %lu failed with error %lu\n", fls_2, GetLastError() );
691 pFlsFree( fls_2 );
692}
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
static int fls(int x)
Definition: bitops.h:157
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define GetProcessHeap()
Definition: compat.h:736
GLsizeiptr size
Definition: glext.h:5919
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
static unsigned int test_fls_callback_call_count
Definition: fiber.c:241
static unsigned int test_fls_chunk_size(unsigned int chunk_index)
Definition: fiber.c:248
#define FLS_TEST_INDEX_COUNT
Definition: fiber.c:220
static HANDLE test_fiberlocalstorage_peb_locked_event
Definition: fiber.c:264
static DWORD WINAPI test_FiberLocalStorage_thread(void *arg)
Definition: fiber.c:268
static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned int *index_in_chunk)
Definition: fiber.c:253
static void WINAPI test_fls_callback(void *data)
Definition: fiber.c:243
static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
Definition: fiber.c:222
static HANDLE test_fiberlocalstorage_done_event
Definition: fiber.c:265
static LIST_ENTRY * fls_list_head
Definition: loader.c:3048
PFLS_CALLBACK_FUNCTION callback
Definition: winternl.h:365
void * unknown
Definition: winternl.h:364
FLS_CALLBACK callbacks[1]
Definition: winternl.h:371
ULONG fls_high_index
Definition: winternl.h:379
FLS_INFO_CHUNK * fls_callback_chunks[8]
Definition: winternl.h:377
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
PVOID * FlsCallback
Definition: winternl.h:551
LIST_ENTRY FlsListHead
Definition: winternl.h:552
PRTL_BITMAP FlsBitmap
Definition: winternl.h:555
ULONG FlsHighIndex
Definition: winternl.h:561
LIST_ENTRY fls_list_entry
Definition: winternl.h:384
void ** fls_data_chunks[8]
Definition: winternl.h:385
PVOID Peb
Definition: compat.h:842
Definition: ps.c:97
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)

Referenced by START_TEST().

◆ test_FiberLocalStorage_thread()

static DWORD WINAPI test_FiberLocalStorage_thread ( void arg)
static

Definition at line 268 of file fiber.c.

269{
270 pRtlAcquirePebLock();
273 pRtlReleasePebLock();
274 return 0;
275}

Referenced by test_FiberLocalStorage().

◆ test_FiberLocalStorageCallback()

static void test_FiberLocalStorageCallback ( PFLS_CALLBACK_FUNCTION  cbfunc)
static

Definition at line 694 of file fiber.c.

695{
696 DWORD fls;
697 BOOL ret;
698 void* val, *val2;
699
700 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
701 {
702 win_skip( "Fiber Local Storage not supported\n" );
703 return;
704 }
705
706 /* Test that the callback is executed */
707 cbCount = 0;
708 fls = pFlsAlloc( cbfunc );
709 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
710
711 val = (void*) 0x1587;
713 ret = pFlsSetValue( fls, val );
714 ok(ret, "FlsSetValue failed with error %lu\n", GetLastError() );
715
716 val2 = pFlsGetValue( fls );
717 ok(val == val2, "FlsGetValue returned %p, expected %p\n", val2, val);
718
719 ret = pFlsFree( fls );
720 ok(ret, "FlsFree failed with error %lu\n", GetLastError() );
721 ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
722
723 /* Test that callback is not executed if value is NULL */
724 cbCount = 0;
725 fls = pFlsAlloc( cbfunc );
726 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
727
728 ret = pFlsSetValue( fls, NULL );
729 ok( ret, "FlsSetValue failed with error %lu\n", GetLastError() );
730
731 pFlsFree( fls );
732 ok( ret, "FlsFree failed with error %lu\n", GetLastError() );
733 ok( cbCount == 0, "Wrong callback count: %d\n", cbCount );
734}

Referenced by START_TEST().

◆ test_FiberLocalStorageWithFibers()

static void test_FiberLocalStorageWithFibers ( PFLS_CALLBACK_FUNCTION  cbfunc)
static

Definition at line 736 of file fiber.c.

737{
738 void* val1 = (void*) 0x314;
739 void* val2 = (void*) 0x152;
740 BOOL ret;
741
742 if (!pFlsAlloc || !pFlsFree || !pFlsSetValue || !pFlsGetValue)
743 {
744 win_skip( "Fiber Local Storage not supported\n" );
745 return;
746 }
747
748 fls_index_to_set = pFlsAlloc(cbfunc);
749 ok(fls_index_to_set != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError());
750
752
753 fiberCount = 0;
754 cbCount = 0;
755 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
756 fibers[2] = pCreateFiber(0,FiberMainProc,&testparam);
757 ok(fibers[1] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
758 ok(fibers[2] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
759 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
760 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
761
762 fiberCount = 0;
763 cbCount = 0;
764 fls_value_to_set = val1;
765 pSwitchToFiber(fibers[1]);
766 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
767 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
768
769 fiberCount = 0;
770 cbCount = 0;
771 fls_value_to_set = val2;
772 pSwitchToFiber(fibers[2]);
773 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
774 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
775
776 fls_value_to_set = val2;
777 ret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
778 ok(ret, "FlsSetValue failed\n");
779 ok(val2 == pFlsGetValue(fls_index_to_set), "FlsGetValue failed\n");
780
781 fiberCount = 0;
782 cbCount = 0;
783 fls_value_to_set = val1;
784 pDeleteFiber(fibers[1]);
785 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
786 ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
787
788 fiberCount = 0;
789 cbCount = 0;
790 fls_value_to_set = val2;
791 pFlsFree(fls_index_to_set);
792 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
793 ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
794
795 fiberCount = 0;
796 cbCount = 0;
797 fls_value_to_set = val1;
798 pDeleteFiber(fibers[2]);
799 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
800 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
801
803}

Referenced by START_TEST().

◆ test_fls_callback()

static void WINAPI test_fls_callback ( void data)
static

Definition at line 243 of file fiber.c.

244{
246}

Referenced by test_FiberLocalStorage().

◆ test_fls_chunk_index_from_index()

static unsigned int test_fls_chunk_index_from_index ( unsigned int  index,
unsigned int index_in_chunk 
)
static

Definition at line 253 of file fiber.c.

254{
255 unsigned int chunk_index = 0;
256
257 while (index >= test_fls_chunk_size(chunk_index))
258 index -= test_fls_chunk_size(chunk_index++);
259
260 *index_in_chunk = index;
261 return chunk_index;
262}

Referenced by test_FiberLocalStorage().

◆ test_fls_chunk_size()

static unsigned int test_fls_chunk_size ( unsigned int  chunk_index)
static

Definition at line 248 of file fiber.c.

249{
250 return 0x10 << chunk_index;
251}

Referenced by test_FiberLocalStorage(), and test_fls_chunk_index_from_index().

◆ test_fls_exit_deadlock()

static void test_fls_exit_deadlock ( void  )
static

Definition at line 1059 of file fiber.c.

1060{
1061 char **argv, cmdline[MAX_PATH];
1063 STARTUPINFOA si = {0};
1064 BOOL ret;
1065
1066 /* Regression test for the following deadlock:
1067 *
1068 * Thread A Thread B
1069 * -----------------------------
1070 * ExitThread
1071 * acquire FLS lock
1072 * call FLS callback
1073 * ExitProcess
1074 * terminate thread A
1075 * acquire FLS lock
1076 *
1077 * Thread B deadlocks on acquiring the FLS lock (in order to itself call its
1078 * FLS callbacks.)
1079 */
1080
1082 sprintf(cmdline, "%s %s fls_exit_deadlock", argv[0], argv[1]);
1084 ok(ret, "failed to create child, error %lu\n", GetLastError());
1086 ok(!ret, "wait failed\n");
1089}
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4749
#define sprintf
Definition: sprintf.c:45
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static SYSTEM_INFO si
Definition: virtual.c:39
TCHAR * cmdline
Definition: stretchblt.cpp:32

Referenced by START_TEST().

◆ thread_actctx_func_early_exit()

static DWORD WINAPI thread_actctx_func_early_exit ( void actctx)
static

Definition at line 908 of file fiber.c.

909{
910 HANDLE exit_thread_fiber;
911
913
914 fibers[1] = pConvertThreadToFiber(NULL);
915 ok(fibers[1] != NULL, "ConvertThreadToFiber returned error %lu\n", GetLastError());
917
918 exit_thread_fiber = pCreateFiber(0, exit_thread_fiber_func, NULL);
919 ok(exit_thread_fiber != NULL, "CreateFiber returned error %lu\n", GetLastError());
920
921 /* exit thread, but keep current fiber */
922 SwitchToFiber(exit_thread_fiber);
924
926 ok(0, "unreachable\n");
927 return 17;
928}
static void WINAPI exit_thread_fiber_func(void *unused)
Definition: fiber.c:898

Referenced by subtest_fiber_actctx_preservation().

◆ void()

static void ( WINAPI pSwitchToFiber)
static

Variable Documentation

◆ cbCount

◆ DWORD

Definition at line 34 of file fiber.c.

◆ fiberCount

int fiberCount = 0
static

Definition at line 53 of file fiber.c.

Referenced by FiberMainProc(), test_FiberHandling(), and test_FiberLocalStorageWithFibers().

◆ fibers

◆ flags

void *static void **static ULONG flags

Definition at line 47 of file fiber.c.

◆ fls_index_to_set

DWORD fls_index_to_set = FLS_OUT_OF_INDEXES
static

Definition at line 50 of file fiber.c.

Referenced by FiberMainProc(), and test_FiberLocalStorageWithFibers().

◆ fls_value_to_set

void* fls_value_to_set
static

◆ LPFIBER_START_ROUTINE

Definition at line 29 of file fiber.c.

◆ LPVOID

Definition at line 29 of file fiber.c.

◆ PVOID

Definition at line 40 of file fiber.c.

◆ SIZE_T

Definition at line 35 of file fiber.c.

◆ test_fiberlocalstorage_done_event

HANDLE test_fiberlocalstorage_done_event
static

Definition at line 265 of file fiber.c.

Referenced by test_FiberLocalStorage(), and test_FiberLocalStorage_thread().

◆ test_fiberlocalstorage_peb_locked_event

HANDLE test_fiberlocalstorage_peb_locked_event
static

Definition at line 264 of file fiber.c.

Referenced by test_FiberLocalStorage(), and test_FiberLocalStorage_thread().

◆ test_fls_callback_call_count

unsigned int test_fls_callback_call_count
static

Definition at line 241 of file fiber.c.

Referenced by test_FiberLocalStorage(), and test_fls_callback().

◆ testparam