Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiber.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS System Libraries 00004 * FILE: lib/kernel32/thread/fiber.c 00005 * PURPOSE: Fiber Implementation 00006 * PROGRAMMERS: 00007 * Alex Ionescu (alex@relsoft.net) 00008 * KJK::Hyperion <noog@libero.it> 00009 */ 00010 #include <k32.h> 00011 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 typedef struct _FIBER /* Field offsets: */ 00016 { /* 32 bit 64 bit */ 00017 /* this must be the first field */ 00018 LPVOID Parameter; /* 0x00 0x00 */ 00019 struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList; /* 0x04 0x08 */ 00020 LPVOID StackBase; /* 0x08 0x10 */ 00021 LPVOID StackLimit; /* 0x0C 0x18 */ 00022 LPVOID DeallocationStack; /* 0x10 0x20 */ 00023 CONTEXT Context; /* 0x14 0x28 */ 00024 ULONG GuaranteedStackBytes; /* 0x2E0 */ 00025 PVOID FlsData; /* 0x2E4 */ 00026 PVOID ActivationContextStack; /* 0x2E8 */ 00027 } FIBER, *PFIBER; 00028 00029 /* PRIVATE FUNCTIONS **********************************************************/ 00030 00031 VOID 00032 WINAPI 00033 BaseRundownFls(IN PVOID FlsData) 00034 { 00035 /* No FLS support yet */ 00036 00037 } 00038 00039 /* PUBLIC FUNCTIONS ***********************************************************/ 00040 00041 /* 00042 * @implemented 00043 */ 00044 BOOL 00045 WINAPI 00046 ConvertFiberToThread(VOID) 00047 { 00048 PTEB Teb; 00049 PFIBER FiberData; 00050 DPRINT1("Converting Fiber to Thread\n"); 00051 00052 /* Check if the thread is already not a fiber */ 00053 Teb = NtCurrentTeb(); 00054 if (!Teb->HasFiberData) 00055 { 00056 /* Fail */ 00057 SetLastError(ERROR_ALREADY_THREAD); 00058 return FALSE; 00059 } 00060 00061 /* this thread won't run a fiber anymore */ 00062 Teb->HasFiberData = FALSE; 00063 FiberData = Teb->NtTib.FiberData; 00064 Teb->NtTib.FiberData = NULL; 00065 00066 /* Free the fiber */ 00067 ASSERT(FiberData != NULL); 00068 RtlFreeHeap(GetProcessHeap(), 0, FiberData); 00069 00070 /* success */ 00071 return TRUE; 00072 } 00073 00074 /* 00075 * @implemented 00076 */ 00077 LPVOID 00078 WINAPI 00079 ConvertThreadToFiberEx(LPVOID lpParameter, 00080 DWORD dwFlags) 00081 { 00082 PTEB Teb; 00083 PFIBER Fiber; 00084 DPRINT1("Converting Thread to Fiber\n"); 00085 00086 /* Check for invalid flags */ 00087 if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH) 00088 { 00089 /* Fail */ 00090 SetLastError(ERROR_INVALID_PARAMETER); 00091 return NULL; 00092 } 00093 00094 /* Are we already a fiber? */ 00095 Teb = NtCurrentTeb(); 00096 if (Teb->HasFiberData) 00097 { 00098 /* Fail */ 00099 SetLastError(ERROR_ALREADY_FIBER); 00100 return NULL; 00101 } 00102 00103 /* Allocate the fiber */ 00104 Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER)); 00105 if (!Fiber) 00106 { 00107 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00108 return NULL; 00109 } 00110 00111 /* Copy some contextual data from the thread to the fiber */ 00112 Fiber->Parameter = lpParameter; 00113 Fiber->ExceptionList = Teb->NtTib.ExceptionList; 00114 Fiber->StackBase = Teb->NtTib.StackBase; 00115 Fiber->StackLimit = Teb->NtTib.StackLimit; 00116 Fiber->DeallocationStack = Teb->DeallocationStack; 00117 Fiber->FlsData = Teb->FlsData; 00118 Fiber->GuaranteedStackBytes = Teb->GuaranteedStackBytes; 00119 Fiber->ActivationContextStack = Teb->ActivationContextStackPointer; 00120 Fiber->Context.ContextFlags = CONTEXT_FULL; 00121 00122 /* Save FPU State if requested */ 00123 if (dwFlags & FIBER_FLAG_FLOAT_SWITCH) 00124 { 00125 Fiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; 00126 } 00127 00128 /* Associate the fiber to the current thread */ 00129 Teb->NtTib.FiberData = Fiber; 00130 Teb->HasFiberData = TRUE; 00131 00132 /* Return opaque fiber data */ 00133 return (LPVOID)Fiber; 00134 } 00135 00136 /* 00137 * @implemented 00138 */ 00139 LPVOID 00140 WINAPI 00141 ConvertThreadToFiber(LPVOID lpParameter) 00142 { 00143 /* Call the newer function */ 00144 return ConvertThreadToFiberEx(lpParameter, 0); 00145 } 00146 00147 /* 00148 * @implemented 00149 */ 00150 LPVOID 00151 WINAPI 00152 CreateFiber(SIZE_T dwStackSize, 00153 LPFIBER_START_ROUTINE lpStartAddress, 00154 LPVOID lpParameter) 00155 { 00156 /* Call the Newer Function */ 00157 return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter); 00158 } 00159 00160 /* 00161 * @implemented 00162 */ 00163 LPVOID 00164 WINAPI 00165 CreateFiberEx(SIZE_T dwStackCommitSize, 00166 SIZE_T dwStackReserveSize, 00167 DWORD dwFlags, 00168 LPFIBER_START_ROUTINE lpStartAddress, 00169 LPVOID lpParameter) 00170 { 00171 PFIBER Fiber; 00172 NTSTATUS Status; 00173 INITIAL_TEB InitialTeb; 00174 PVOID ActivationContextStack = NULL; 00175 DPRINT("Creating Fiber\n"); 00176 00177 /* Check for invalid flags */ 00178 if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH) 00179 { 00180 /* Fail */ 00181 SetLastError(ERROR_INVALID_PARAMETER); 00182 return NULL; 00183 } 00184 00185 /* Allocate the Activation Context Stack */ 00186 Status = RtlAllocateActivationContextStack(&ActivationContextStack); 00187 if (!NT_SUCCESS(Status)) 00188 { 00189 /* Fail */ 00190 BaseSetLastNTError(Status); 00191 return NULL; 00192 } 00193 00194 /* Allocate the fiber */ 00195 Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER)); 00196 if (!Fiber) 00197 { 00198 /* Fail */ 00199 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00200 return NULL; 00201 } 00202 00203 /* Create the stack for the fiber */ 00204 Status = BaseCreateStack(NtCurrentProcess(), 00205 dwStackCommitSize, 00206 dwStackReserveSize, 00207 &InitialTeb); 00208 if (!NT_SUCCESS(Status)) 00209 { 00210 /* Free the fiber */ 00211 RtlFreeHeap(GetProcessHeap(), 0, Fiber); 00212 00213 /* Free the activation context */ 00214 DPRINT1("Leaking activation stack because nobody implemented free"); 00215 //RtlFreeActivationContextStack(&ActivationContextStack); 00216 00217 /* Failure */ 00218 BaseSetLastNTError(Status); 00219 return NULL; 00220 } 00221 00222 /* Clear the context */ 00223 RtlZeroMemory(&Fiber->Context, sizeof(CONTEXT)); 00224 00225 /* Copy the data into the fiber */ 00226 Fiber->StackBase = InitialTeb.StackBase; 00227 Fiber->StackLimit = InitialTeb.StackLimit; 00228 Fiber->DeallocationStack = InitialTeb.AllocatedStackBase; 00229 Fiber->Parameter = lpParameter; 00230 Fiber->ExceptionList = EXCEPTION_CHAIN_END; 00231 Fiber->GuaranteedStackBytes = 0; 00232 Fiber->FlsData = NULL; 00233 Fiber->ActivationContextStack = ActivationContextStack; 00234 Fiber->Context.ContextFlags = CONTEXT_FULL; 00235 00236 /* Save FPU State if requested */ 00237 Fiber->Context.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ? CONTEXT_FLOATING_POINT : 0; 00238 00239 /* initialize the context for the fiber */ 00240 BaseInitializeContext(&Fiber->Context, 00241 lpParameter, 00242 lpStartAddress, 00243 InitialTeb.StackBase, 00244 2); 00245 00246 /* Return the Fiber */ 00247 return Fiber; 00248 } 00249 00250 /* 00251 * @implemented 00252 */ 00253 VOID 00254 WINAPI 00255 DeleteFiber(LPVOID lpFiber) 00256 { 00257 SIZE_T Size = 0; 00258 PFIBER Fiber = (PFIBER)lpFiber; 00259 PTEB Teb; 00260 00261 /* First, exit the thread */ 00262 Teb = NtCurrentTeb(); 00263 if ((Teb->HasFiberData) && (Teb->NtTib.FiberData == Fiber)) ExitThread(1); 00264 00265 /* Now de-allocate the stack */ 00266 NtFreeVirtualMemory(NtCurrentProcess(), 00267 &Fiber->DeallocationStack, 00268 &Size, 00269 MEM_RELEASE); 00270 00271 /* Get rid of FLS */ 00272 if (Fiber->FlsData) BaseRundownFls(Fiber->FlsData); 00273 00274 /* Get rid of the activation stack */ 00275 DPRINT1("Leaking activation stack because nobody implemented free"); 00276 //RtlFreeActivationContextStack(Fiber->ActivationContextStack); 00277 00278 /* Free the fiber data */ 00279 RtlFreeHeap(GetProcessHeap(), 0, lpFiber); 00280 } 00281 00282 /* 00283 * @implemented 00284 */ 00285 BOOL 00286 WINAPI 00287 IsThreadAFiber(VOID) 00288 { 00289 return NtCurrentTeb()->HasFiberData; 00290 } 00291 00292 /* 00293 * @unimplemented 00294 */ 00295 DWORD 00296 WINAPI 00297 FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) 00298 { 00299 (void)lpCallback; 00300 00301 UNIMPLEMENTED; 00302 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 00303 return FLS_OUT_OF_INDEXES; 00304 } 00305 00306 00307 /* 00308 * @unimplemented 00309 */ 00310 BOOL 00311 WINAPI 00312 FlsFree(DWORD dwFlsIndex) 00313 { 00314 (void)dwFlsIndex; 00315 00316 UNIMPLEMENTED; 00317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 00318 return FALSE; 00319 } 00320 00321 00322 /* 00323 * @implemented 00324 */ 00325 PVOID 00326 WINAPI 00327 FlsGetValue(DWORD dwFlsIndex) 00328 { 00329 PVOID *ppFlsSlots; 00330 PVOID pRetVal; 00331 00332 if(dwFlsIndex >= 128) goto l_InvalidParam; 00333 00334 ppFlsSlots = NtCurrentTeb()->FlsData; 00335 00336 if(ppFlsSlots == NULL) goto l_InvalidParam; 00337 00338 SetLastError(0); 00339 pRetVal = ppFlsSlots[dwFlsIndex + 2]; 00340 00341 return pRetVal; 00342 00343 l_InvalidParam: 00344 SetLastError(ERROR_INVALID_PARAMETER); 00345 return NULL; 00346 } 00347 00348 00349 /* 00350 * @implemented 00351 */ 00352 BOOL 00353 WINAPI 00354 FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData) 00355 { 00356 PVOID *ppFlsSlots; 00357 TEB *pTeb = NtCurrentTeb(); 00358 00359 if(dwFlsIndex >= 128) goto l_InvalidParam; 00360 00361 ppFlsSlots = pTeb->FlsData; 00362 00363 if (ppFlsSlots == NULL) 00364 { 00365 PEB *pPeb = pTeb->ProcessEnvironmentBlock; 00366 00367 ppFlsSlots = RtlAllocateHeap(pPeb->ProcessHeap, 00368 HEAP_ZERO_MEMORY, 00369 (128 + 2) * sizeof(PVOID)); 00370 if(ppFlsSlots == NULL) goto l_OutOfMemory; 00371 00372 pTeb->FlsData = ppFlsSlots; 00373 00374 RtlAcquirePebLock(); 00375 00376 /* TODO: initialization */ 00377 00378 RtlReleasePebLock(); 00379 } 00380 00381 ppFlsSlots[dwFlsIndex + 2] = lpFlsData; 00382 00383 return TRUE; 00384 00385 l_OutOfMemory: 00386 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00387 goto l_Fail; 00388 00389 l_InvalidParam: 00390 SetLastError(ERROR_INVALID_PARAMETER); 00391 00392 l_Fail: 00393 return FALSE; 00394 } 00395 00396 /* EOF */ Generated on Sun May 27 2012 04:24:25 for ReactOS by
1.7.6.1
|