2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS System Libraries
4 * FILE: lib/kernel32/thread/fiber.c
5 * PURPOSE: Fiber Implementation
7 * Alex Ionescu (alex@relsoft.net)
8 * KJK::Hyperion <noog@libero.it>
15 typedef struct _FIBER
/* Field offsets: */
17 /* this must be the first field */
18 LPVOID Parameter
; /* 0x00 0x00 */
19 struct _EXCEPTION_REGISTRATION_RECORD
* ExceptionList
; /* 0x04 0x08 */
20 LPVOID StackBase
; /* 0x08 0x10 */
21 LPVOID StackLimit
; /* 0x0C 0x18 */
22 LPVOID DeallocationStack
; /* 0x10 0x20 */
23 CONTEXT Context
; /* 0x14 0x28 */
24 ULONG GuaranteedStackBytes
; /* 0x2E0 */
25 PVOID FlsData
; /* 0x2E4 */
26 PVOID ActivationContextStack
; /* 0x2E8 */
34 ConvertFiberToThread(VOID
)
36 PTEB pTeb
= NtCurrentTeb();
37 DPRINT1("Converting Fiber to Thread\n");
39 /* the current thread isn't running a fiber: failure */
40 if (!pTeb
->HasFiberData
)
42 SetLastError(ERROR_INVALID_PARAMETER
);
46 /* this thread won't run a fiber anymore */
47 pTeb
->HasFiberData
= FALSE
;
50 if (pTeb
->Tib
.FiberData
!= NULL
)
52 RtlFreeHeap(GetProcessHeap(), 0, pTeb
->Tib
.FiberData
);
64 ConvertThreadToFiberEx(LPVOID lpParameter
,
67 PTEB pTeb
= NtCurrentTeb();
69 DPRINT1("Converting Thread to Fiber\n");
71 /* the current thread is already a fiber */
72 if (pTeb
->HasFiberData
&& pTeb
->Tib
.FiberData
)
73 return pTeb
->Tib
.FiberData
;
75 /* allocate the fiber */
76 pfCurFiber
= (PFIBER
)RtlAllocateHeap(GetProcessHeap(),
81 if (pfCurFiber
== NULL
)
83 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
87 /* copy some contextual data from the thread to the fiber */
88 pfCurFiber
->Parameter
= lpParameter
;
89 pfCurFiber
->ExceptionList
= pTeb
->Tib
.ExceptionList
;
90 pfCurFiber
->StackBase
= pTeb
->Tib
.StackBase
;
91 pfCurFiber
->StackLimit
= pTeb
->Tib
.StackLimit
;
92 pfCurFiber
->DeallocationStack
= pTeb
->DeallocationStack
;
93 pfCurFiber
->FlsData
= pTeb
->FlsData
;
94 pfCurFiber
->GuaranteedStackBytes
= pTeb
->GuaranteedStackBytes
;
95 pfCurFiber
->ActivationContextStack
= pTeb
->ActivationContextStackPointer
;
96 pfCurFiber
->Context
.ContextFlags
= CONTEXT_FULL
;
98 /* Save FPU State if requsted */
99 if (dwFlags
& FIBER_FLAG_FLOAT_SWITCH
)
101 pfCurFiber
->Context
.ContextFlags
|= CONTEXT_FLOATING_POINT
;
104 /* associate the fiber to the current thread */
105 pTeb
->Tib
.FiberData
= pfCurFiber
;
106 pTeb
->HasFiberData
= TRUE
;
109 return (LPVOID
)pfCurFiber
;
117 ConvertThreadToFiber(LPVOID lpParameter
)
119 /* Call the newer function */
120 return ConvertThreadToFiberEx(lpParameter
, 0);
128 CreateFiber(SIZE_T dwStackSize
,
129 LPFIBER_START_ROUTINE lpStartAddress
,
132 /* Call the Newer Function */
133 return CreateFiberEx(dwStackSize
, 0, 0, lpStartAddress
, lpParameter
);
141 CreateFiberEx(SIZE_T dwStackCommitSize
,
142 SIZE_T dwStackReserveSize
,
144 LPFIBER_START_ROUTINE lpStartAddress
,
149 INITIAL_TEB usFiberInitialTeb
;
150 CONTEXT ctxFiberContext
;
151 PVOID ActivationContextStack
= NULL
;
152 DPRINT1("Creating Fiber\n");
154 #ifdef SXS_SUPPORT_ENABLED
155 /* Allocate the Activation Context Stack */
156 nErrCode
= RtlAllocateActivationContextStack(&ActivationContextStack
);
159 /* Allocate the fiber */
160 pfCurFiber
= (PFIBER
)RtlAllocateHeap(GetProcessHeap(),
164 if (pfCurFiber
== NULL
)
166 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
170 /* Create the stack for the fiber */
171 nErrCode
= BasepCreateStack(NtCurrentProcess(),
176 if(!NT_SUCCESS(nErrCode
))
179 RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber
);
182 SetLastErrorByStatus(nErrCode
);
186 /* Clear the context */
187 RtlZeroMemory(&pfCurFiber
->Context
, sizeof(CONTEXT
));
189 /* copy the data into the fiber */
190 pfCurFiber
->StackBase
= usFiberInitialTeb
.StackBase
;
191 pfCurFiber
->StackLimit
= usFiberInitialTeb
.StackLimit
;
192 pfCurFiber
->DeallocationStack
= usFiberInitialTeb
.AllocatedStackBase
;
193 pfCurFiber
->Parameter
= lpParameter
;
194 pfCurFiber
->ExceptionList
= (struct _EXCEPTION_REGISTRATION_RECORD
*)-1;
195 pfCurFiber
->GuaranteedStackBytes
= 0;
196 pfCurFiber
->FlsData
= NULL
;
197 pfCurFiber
->ActivationContextStack
= ActivationContextStack
;
198 pfCurFiber
->Context
.ContextFlags
= CONTEXT_FULL
;
200 /* Save FPU State if requsted */
201 if (dwFlags
& FIBER_FLAG_FLOAT_SWITCH
)
203 pfCurFiber
->Context
.ContextFlags
|= CONTEXT_FLOATING_POINT
;
206 /* initialize the context for the fiber */
207 BasepInitializeContext(&ctxFiberContext
,
210 usFiberInitialTeb
.StackBase
,
213 /* Return the Fiber */
222 DeleteFiber(LPVOID lpFiber
)
225 PVOID pStackAllocBase
= ((PFIBER
)lpFiber
)->DeallocationStack
;
228 RtlFreeHeap(GetProcessHeap(), 0, lpFiber
);
230 /* the fiber is deleting itself: let the system deallocate the stack */
231 if (NtCurrentTeb()->Tib
.FiberData
== lpFiber
)
234 /* deallocate the stack */
235 NtFreeVirtualMemory(NtCurrentProcess(),
248 return NtCurrentTeb()->HasFiberData
;
255 BaseFiberStartup(VOID
)
258 PFIBER Fiber
= GetFiberData();
260 /* Call the Thread Startup Routine */
261 DPRINT1("Starting Fiber\n");
262 BaseThreadStartup((LPTHREAD_START_ROUTINE
)Fiber
->Context
.Eax
,
263 (LPVOID
)Fiber
->Context
.Ebx
);
265 #warning Unknown architecture