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
->NtTib
.FiberData
!= NULL
)
52 RtlFreeHeap(GetProcessHeap(), 0, pTeb
->NtTib
.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
->NtTib
.FiberData
) return pTeb
->NtTib
.FiberData
;
74 /* allocate the fiber */
75 pfCurFiber
= (PFIBER
)RtlAllocateHeap(GetProcessHeap(),
80 if (pfCurFiber
== NULL
)
82 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
86 /* copy some contextual data from the thread to the fiber */
87 pfCurFiber
->Parameter
= lpParameter
;
88 pfCurFiber
->ExceptionList
= pTeb
->NtTib
.ExceptionList
;
89 pfCurFiber
->StackBase
= pTeb
->NtTib
.StackBase
;
90 pfCurFiber
->StackLimit
= pTeb
->NtTib
.StackLimit
;
91 pfCurFiber
->DeallocationStack
= pTeb
->DeallocationStack
;
92 pfCurFiber
->FlsData
= pTeb
->FlsData
;
93 pfCurFiber
->GuaranteedStackBytes
= pTeb
->GuaranteedStackBytes
;
94 pfCurFiber
->ActivationContextStack
= pTeb
->ActivationContextStackPointer
;
95 pfCurFiber
->Context
.ContextFlags
= CONTEXT_FULL
;
97 /* Save FPU State if requsted */
98 if (dwFlags
& FIBER_FLAG_FLOAT_SWITCH
)
100 pfCurFiber
->Context
.ContextFlags
|= CONTEXT_FLOATING_POINT
;
103 /* associate the fiber to the current thread */
104 pTeb
->NtTib
.FiberData
= pfCurFiber
;
105 pTeb
->HasFiberData
= TRUE
;
108 return (LPVOID
)pfCurFiber
;
116 ConvertThreadToFiber(LPVOID lpParameter
)
118 /* Call the newer function */
119 return ConvertThreadToFiberEx(lpParameter
, 0);
127 CreateFiber(SIZE_T dwStackSize
,
128 LPFIBER_START_ROUTINE lpStartAddress
,
131 /* Call the Newer Function */
132 return CreateFiberEx(dwStackSize
, 0, 0, lpStartAddress
, lpParameter
);
140 CreateFiberEx(SIZE_T dwStackCommitSize
,
141 SIZE_T dwStackReserveSize
,
143 LPFIBER_START_ROUTINE lpStartAddress
,
148 INITIAL_TEB usFiberInitialTeb
;
149 PVOID ActivationContextStack
= NULL
;
150 DPRINT("Creating Fiber\n");
152 #ifdef SXS_SUPPORT_ENABLED
153 /* Allocate the Activation Context Stack */
154 nErrCode
= RtlAllocateActivationContextStack(&ActivationContextStack
);
157 /* Allocate the fiber */
158 pfCurFiber
= (PFIBER
)RtlAllocateHeap(GetProcessHeap(),
162 if (pfCurFiber
== NULL
)
164 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
168 /* Create the stack for the fiber */
169 nErrCode
= BasepCreateStack(NtCurrentProcess(),
174 if(!NT_SUCCESS(nErrCode
))
177 RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber
);
180 SetLastErrorByStatus(nErrCode
);
184 /* Clear the context */
185 RtlZeroMemory(&pfCurFiber
->Context
, sizeof(CONTEXT
));
187 /* copy the data into the fiber */
188 pfCurFiber
->StackBase
= usFiberInitialTeb
.StackBase
;
189 pfCurFiber
->StackLimit
= usFiberInitialTeb
.StackLimit
;
190 pfCurFiber
->DeallocationStack
= usFiberInitialTeb
.AllocatedStackBase
;
191 pfCurFiber
->Parameter
= lpParameter
;
192 pfCurFiber
->ExceptionList
= (struct _EXCEPTION_REGISTRATION_RECORD
*)-1;
193 pfCurFiber
->GuaranteedStackBytes
= 0;
194 pfCurFiber
->FlsData
= NULL
;
195 pfCurFiber
->ActivationContextStack
= ActivationContextStack
;
196 pfCurFiber
->Context
.ContextFlags
= CONTEXT_FULL
;
198 /* Save FPU State if requsted */
199 if (dwFlags
& FIBER_FLAG_FLOAT_SWITCH
)
201 pfCurFiber
->Context
.ContextFlags
|= CONTEXT_FLOATING_POINT
;
204 /* initialize the context for the fiber */
205 BasepInitializeContext(&pfCurFiber
->Context
,
208 usFiberInitialTeb
.StackBase
,
211 /* Return the Fiber */
220 DeleteFiber(LPVOID lpFiber
)
223 PVOID pStackAllocBase
= ((PFIBER
)lpFiber
)->DeallocationStack
;
226 RtlFreeHeap(GetProcessHeap(), 0, lpFiber
);
228 /* the fiber is deleting itself: let the system deallocate the stack */
229 if(NtCurrentTeb()->NtTib
.FiberData
== lpFiber
) ExitThread(1);
231 /* deallocate the stack */
232 NtFreeVirtualMemory(NtCurrentProcess(),
245 return NtCurrentTeb()->HasFiberData
;
252 BaseFiberStartup(VOID
)
255 PFIBER Fiber
= GetCurrentFiber();
257 /* Call the Thread Startup Routine */
258 DPRINT("Starting Fiber\n");
259 BaseThreadStartup((LPTHREAD_START_ROUTINE
)Fiber
->Context
.Eax
,
260 (LPVOID
)Fiber
->Context
.Ebx
);
262 #warning Unknown architecture