ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fiber.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.