Commit 3268601d authored by Jinoh Kang's avatar Jinoh Kang Committed by Alexandre Julliard

kernelbase: Implement activation context switching for fibers.

parent 7c4eb574
...@@ -839,7 +839,7 @@ static void WINAPI fiber_actctx_func(void *actctx) ...@@ -839,7 +839,7 @@ static void WINAPI fiber_actctx_func(void *actctx)
HANDLE thread; HANDLE thread;
BOOL ret; BOOL ret;
check_current_actctx_is(NULL, TRUE); check_current_actctx_is(NULL, FALSE);
ret = ActivateActCtx(actctx, &cookie); ret = ActivateActCtx(actctx, &cookie);
ok(ret, "ActivateActCtx returned error %lu\n", GetLastError()); ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
...@@ -858,7 +858,7 @@ static void WINAPI fiber_actctx_func(void *actctx) ...@@ -858,7 +858,7 @@ static void WINAPI fiber_actctx_func(void *actctx)
ret = DeactivateActCtx(0, cookie); ret = DeactivateActCtx(0, cookie);
ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError()); ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
check_current_actctx_is(NULL, TRUE); check_current_actctx_is(NULL, FALSE);
SwitchToFiber(fibers[0]); SwitchToFiber(fibers[0]);
ok(0, "unreachable\n"); ok(0, "unreachable\n");
...@@ -872,10 +872,10 @@ static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actc ...@@ -872,10 +872,10 @@ static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actc
check_current_actctx_is(current_actctx, FALSE); check_current_actctx_is(current_actctx, FALSE);
SwitchToFiber(fibers[1]); SwitchToFiber(fibers[1]);
check_current_actctx_is(current_actctx, TRUE); check_current_actctx_is(current_actctx, FALSE);
SwitchToFiber(fibers[1]); SwitchToFiber(fibers[1]);
check_current_actctx_is(current_actctx, TRUE); check_current_actctx_is(current_actctx, FALSE);
SwitchToFiber(fibers[2]); SwitchToFiber(fibers[2]);
check_current_actctx_is(current_actctx, FALSE); check_current_actctx_is(current_actctx, FALSE);
...@@ -910,7 +910,7 @@ static DWORD WINAPI thread_actctx_func_early_exit(void *actctx) ...@@ -910,7 +910,7 @@ static DWORD WINAPI thread_actctx_func_early_exit(void *actctx)
/* exit thread, but keep current fiber */ /* exit thread, but keep current fiber */
SwitchToFiber(exit_thread_fiber); SwitchToFiber(exit_thread_fiber);
check_current_actctx_is(actctx, TRUE); check_current_actctx_is(actctx, FALSE);
SwitchToFiber(fibers[0]); SwitchToFiber(fibers[0]);
ok(0, "unreachable\n"); ok(0, "unreachable\n");
......
...@@ -768,6 +768,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH TlsSetValue( DWORD index, LPVOID value ) ...@@ -768,6 +768,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH TlsSetValue( DWORD index, LPVOID value )
***********************************************************************/ ***********************************************************************/
struct fiber_actctx
{
ACTIVATION_CONTEXT_STACK stack_space; /* activation context stack space */
ACTIVATION_CONTEXT_STACK *stack_ptr; /* last value of ActivationContextStackPointer */
};
struct fiber_data struct fiber_data
{ {
LPVOID param; /* 00/00 fiber param */ LPVOID param; /* 00/00 fiber param */
...@@ -779,6 +785,7 @@ struct fiber_data ...@@ -779,6 +785,7 @@ struct fiber_data
DWORD flags; /* fiber flags */ DWORD flags; /* fiber flags */
LPFIBER_START_ROUTINE start; /* start routine */ LPFIBER_START_ROUTINE start; /* start routine */
void *fls_slots; /* fiber storage slots */ void *fls_slots; /* fiber storage slots */
struct fiber_actctx actctx; /* activation context state */
}; };
extern void WINAPI switch_fiber( CONTEXT *old, CONTEXT *new ); extern void WINAPI switch_fiber( CONTEXT *old, CONTEXT *new );
...@@ -931,6 +938,38 @@ static void init_fiber_context( struct fiber_data *fiber ) ...@@ -931,6 +938,38 @@ static void init_fiber_context( struct fiber_data *fiber )
#endif #endif
} }
static void move_list( LIST_ENTRY *dest, LIST_ENTRY *src )
{
LIST_ENTRY *head = src->Flink;
LIST_ENTRY *tail = src->Blink;
if (src != head)
{
dest->Flink = head;
dest->Blink = tail;
head->Blink = dest;
tail->Flink = dest;
}
else InitializeListHead( dest );
}
static void relocate_thread_actctx_stack( ACTIVATION_CONTEXT_STACK *dest )
{
ACTIVATION_CONTEXT_STACK *src = NtCurrentTeb()->ActivationContextStackPointer;
C_ASSERT(sizeof(*dest) == sizeof(dest->ActiveFrame) + sizeof(dest->FrameListCache) +
sizeof(dest->Flags) + sizeof(dest->NextCookieSequenceNumber) +
sizeof(dest->StackId));
dest->ActiveFrame = src->ActiveFrame;
move_list( &dest->FrameListCache, &src->FrameListCache );
dest->Flags = src->Flags;
dest->NextCookieSequenceNumber = src->NextCookieSequenceNumber;
dest->StackId = src->StackId;
NtCurrentTeb()->ActivationContextStackPointer = dest;
}
/*********************************************************************** /***********************************************************************
* CreateFiber (kernelbase.@) * CreateFiber (kernelbase.@)
...@@ -969,6 +1008,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH CreateFiberEx( SIZE_T stack_commit, SIZE_T stack ...@@ -969,6 +1008,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH CreateFiberEx( SIZE_T stack_commit, SIZE_T stack
fiber->except = (void *)-1; fiber->except = (void *)-1;
fiber->start = start; fiber->start = start;
fiber->flags = flags; fiber->flags = flags;
InitializeListHead( &fiber->actctx.stack_space.FrameListCache );
fiber->actctx.stack_ptr = &fiber->actctx.stack_space;
init_fiber_context( fiber ); init_fiber_context( fiber );
return fiber; return fiber;
} }
...@@ -983,6 +1024,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH ConvertFiberToThread(void) ...@@ -983,6 +1024,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH ConvertFiberToThread(void)
if (fiber) if (fiber)
{ {
relocate_thread_actctx_stack( &NtCurrentTeb()->ActivationContextStack );
NtCurrentTeb()->Tib.u.FiberData = NULL; NtCurrentTeb()->Tib.u.FiberData = NULL;
HeapFree( GetProcessHeap(), 0, fiber ); HeapFree( GetProcessHeap(), 0, fiber );
} }
...@@ -1025,6 +1067,7 @@ LPVOID WINAPI DECLSPEC_HOTPATCH ConvertThreadToFiberEx( LPVOID param, DWORD flag ...@@ -1025,6 +1067,7 @@ LPVOID WINAPI DECLSPEC_HOTPATCH ConvertThreadToFiberEx( LPVOID param, DWORD flag
fiber->start = NULL; fiber->start = NULL;
fiber->flags = flags; fiber->flags = flags;
fiber->fls_slots = NtCurrentTeb()->FlsSlots; fiber->fls_slots = NtCurrentTeb()->FlsSlots;
relocate_thread_actctx_stack( &fiber->actctx.stack_space );
NtCurrentTeb()->Tib.u.FiberData = fiber; NtCurrentTeb()->Tib.u.FiberData = fiber;
return fiber; return fiber;
} }
...@@ -1040,11 +1083,13 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr ) ...@@ -1040,11 +1083,13 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr )
if (!fiber) return; if (!fiber) return;
if (fiber == NtCurrentTeb()->Tib.u.FiberData) if (fiber == NtCurrentTeb()->Tib.u.FiberData)
{ {
relocate_thread_actctx_stack( &NtCurrentTeb()->ActivationContextStack );
HeapFree( GetProcessHeap(), 0, fiber ); HeapFree( GetProcessHeap(), 0, fiber );
RtlExitUserThread( 1 ); RtlExitUserThread( 1 );
} }
RtlFreeUserStack( fiber->stack_allocation ); RtlFreeUserStack( fiber->stack_allocation );
RtlProcessFlsData( fiber->fls_slots, 3 ); RtlProcessFlsData( fiber->fls_slots, 3 );
RtlFreeActivationContextStack( &fiber->actctx.stack_space );
HeapFree( GetProcessHeap(), 0, fiber ); HeapFree( GetProcessHeap(), 0, fiber );
} }
...@@ -1069,6 +1114,7 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber ) ...@@ -1069,6 +1114,7 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber )
current_fiber->except = NtCurrentTeb()->Tib.ExceptionList; current_fiber->except = NtCurrentTeb()->Tib.ExceptionList;
current_fiber->stack_limit = NtCurrentTeb()->Tib.StackLimit; current_fiber->stack_limit = NtCurrentTeb()->Tib.StackLimit;
current_fiber->fls_slots = NtCurrentTeb()->FlsSlots; current_fiber->fls_slots = NtCurrentTeb()->FlsSlots;
current_fiber->actctx.stack_ptr = NtCurrentTeb()->ActivationContextStackPointer;
/* stack_allocation and stack_base never change */ /* stack_allocation and stack_base never change */
/* FIXME: should save floating point context if requested in fiber->flags */ /* FIXME: should save floating point context if requested in fiber->flags */
...@@ -1078,6 +1124,7 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber ) ...@@ -1078,6 +1124,7 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber )
NtCurrentTeb()->Tib.StackLimit = new_fiber->stack_limit; NtCurrentTeb()->Tib.StackLimit = new_fiber->stack_limit;
NtCurrentTeb()->DeallocationStack = new_fiber->stack_allocation; NtCurrentTeb()->DeallocationStack = new_fiber->stack_allocation;
NtCurrentTeb()->FlsSlots = new_fiber->fls_slots; NtCurrentTeb()->FlsSlots = new_fiber->fls_slots;
NtCurrentTeb()->ActivationContextStackPointer = new_fiber->actctx.stack_ptr;
switch_fiber( &current_fiber->context, &new_fiber->context ); switch_fiber( &current_fiber->context, &new_fiber->context );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment