~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/kernel32/fiber.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Fiber support
  3  *
  4  * Copyright 2002 Alexandre Julliard
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  *
 20  * FIXME:
 21  * - proper handling of 16-bit stack and signal stack
 22  */
 23 
 24 /* Fortify source chokes on siglongjmp stack switching, so disable it */
 25 #undef _FORTIFY_SOURCE
 26 #define _FORTIFY_SOURCE 0
 27 
 28 #include "config.h"
 29 #include "wine/port.h"
 30 
 31 #include <setjmp.h>
 32 #include <stdarg.h>
 33 
 34 #define NONAMELESSUNION
 35 #include "windef.h"
 36 #include "winbase.h"
 37 #include "winerror.h"
 38 #include "winternl.h"
 39 #include "wine/exception.h"
 40 #include "wine/library.h"
 41 
 42 struct fiber_data
 43 {
 44     LPVOID                param;             /* 00 fiber param */
 45     void                 *except;            /* 04 saved exception handlers list */
 46     void                 *stack_base;        /* 08 top of fiber stack */
 47     void                 *stack_limit;       /* 0c fiber stack low-water mark */
 48     void                 *stack_allocation;  /* 10 base of the fiber stack allocation */
 49     sigjmp_buf            jmpbuf;            /* 14 setjmp buffer (on Windows: CONTEXT) */
 50     DWORD                 flags;             /*    fiber flags */
 51     LPFIBER_START_ROUTINE start;             /*    start routine */
 52     void                **fls_slots;         /*    fiber storage slots */
 53 };
 54 
 55 
 56 /* call the fiber initial function once we have switched stack */
 57 static void start_fiber( void *arg )
 58 {
 59     struct fiber_data *fiber = arg;
 60     LPFIBER_START_ROUTINE start = fiber->start;
 61 
 62     __TRY
 63     {
 64         fiber->start = NULL;
 65         start( fiber->param );
 66         ExitThread( 1 );
 67     }
 68     __EXCEPT(UnhandledExceptionFilter)
 69     {
 70         TerminateThread( GetCurrentThread(), GetExceptionCode() );
 71     }
 72     __ENDTRY
 73 }
 74 
 75 
 76 /***********************************************************************
 77  *           CreateFiber   (KERNEL32.@)
 78  */
 79 LPVOID WINAPI CreateFiber( SIZE_T stack, LPFIBER_START_ROUTINE start, LPVOID param )
 80 {
 81     return CreateFiberEx( stack, 0, 0, start, param );
 82 }
 83 
 84 
 85 /***********************************************************************
 86  *           CreateFiberEx   (KERNEL32.@)
 87  */
 88 LPVOID WINAPI CreateFiberEx( SIZE_T stack_commit, SIZE_T stack_reserve, DWORD flags,
 89                              LPFIBER_START_ROUTINE start, LPVOID param )
 90 {
 91     struct fiber_data *fiber;
 92 
 93     if (!(fiber = HeapAlloc( GetProcessHeap(), 0, sizeof(*fiber) )))
 94     {
 95         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
 96         return NULL;
 97     }
 98 
 99     /* FIXME: should use the thread stack allocation routines here */
100     if (!stack_reserve) stack_reserve = 1024*1024;
101     if(!(fiber->stack_allocation = VirtualAlloc( 0, stack_reserve, MEM_COMMIT, PAGE_READWRITE )))
102     {
103         HeapFree( GetProcessHeap(), 0, fiber );
104         return NULL;
105     }
106     fiber->stack_base  = (char *)fiber->stack_allocation + stack_reserve;
107     fiber->stack_limit = fiber->stack_allocation;
108     fiber->param       = param;
109     fiber->except      = (void *)-1;
110     fiber->start       = start;
111     fiber->flags       = flags;
112     fiber->fls_slots   = NULL;
113     return fiber;
114 }
115 
116 
117 /***********************************************************************
118  *           DeleteFiber   (KERNEL32.@)
119  */
120 void WINAPI DeleteFiber( LPVOID fiber_ptr )
121 {
122     struct fiber_data *fiber = fiber_ptr;
123 
124     if (!fiber) return;
125     if (fiber == NtCurrentTeb()->Tib.u.FiberData)
126     {
127         HeapFree( GetProcessHeap(), 0, fiber );
128         ExitThread(1);
129     }
130     VirtualFree( fiber->stack_allocation, 0, MEM_RELEASE );
131     HeapFree( GetProcessHeap(), 0, fiber->fls_slots );
132     HeapFree( GetProcessHeap(), 0, fiber );
133 }
134 
135 
136 /***********************************************************************
137  *           ConvertThreadToFiber   (KERNEL32.@)
138  */
139 LPVOID WINAPI ConvertThreadToFiber( LPVOID param )
140 {
141     return ConvertThreadToFiberEx( param, 0 );
142 }
143 
144 
145 /***********************************************************************
146  *           ConvertThreadToFiberEx   (KERNEL32.@)
147  */
148 LPVOID WINAPI ConvertThreadToFiberEx( LPVOID param, DWORD flags )
149 {
150     struct fiber_data *fiber;
151 
152     if (!(fiber = HeapAlloc( GetProcessHeap(), 0, sizeof(*fiber) )))
153     {
154         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
155         return NULL;
156     }
157     fiber->param            = param;
158     fiber->except           = NtCurrentTeb()->Tib.ExceptionList;
159     fiber->stack_base       = NtCurrentTeb()->Tib.StackBase;
160     fiber->stack_limit      = NtCurrentTeb()->Tib.StackLimit;
161     fiber->stack_allocation = NtCurrentTeb()->DeallocationStack;
162     fiber->start            = NULL;
163     fiber->flags            = flags;
164     fiber->fls_slots        = NtCurrentTeb()->FlsSlots;
165     NtCurrentTeb()->Tib.u.FiberData = fiber;
166     return fiber;
167 }
168 
169 
170 /***********************************************************************
171  *           ConvertFiberToThread   (KERNEL32.@)
172  */
173 BOOL WINAPI ConvertFiberToThread(void)
174 {
175     struct fiber_data *fiber = NtCurrentTeb()->Tib.u.FiberData;
176 
177     if (fiber)
178     {
179         NtCurrentTeb()->Tib.u.FiberData = NULL;
180         HeapFree( GetProcessHeap(), 0, fiber );
181     }
182     return TRUE;
183 }
184 
185 
186 /***********************************************************************
187  *           SwitchToFiber   (KERNEL32.@)
188  */
189 void WINAPI SwitchToFiber( LPVOID fiber )
190 {
191     struct fiber_data *new_fiber = fiber;
192     struct fiber_data *current_fiber = NtCurrentTeb()->Tib.u.FiberData;
193 
194     current_fiber->except      = NtCurrentTeb()->Tib.ExceptionList;
195     current_fiber->stack_limit = NtCurrentTeb()->Tib.StackLimit;
196     current_fiber->fls_slots   = NtCurrentTeb()->FlsSlots;
197     /* stack_allocation and stack_base never change */
198 
199     /* FIXME: should save floating point context if requested in fiber->flags */
200     if (!sigsetjmp( current_fiber->jmpbuf, 0 ))
201     {
202         NtCurrentTeb()->Tib.u.FiberData   = new_fiber;
203         NtCurrentTeb()->Tib.ExceptionList = new_fiber->except;
204         NtCurrentTeb()->Tib.StackBase     = new_fiber->stack_base;
205         NtCurrentTeb()->Tib.StackLimit    = new_fiber->stack_limit;
206         NtCurrentTeb()->DeallocationStack = new_fiber->stack_allocation;
207         NtCurrentTeb()->FlsSlots          = new_fiber->fls_slots;
208         if (new_fiber->start)  /* first time */
209             wine_switch_to_stack( start_fiber, new_fiber, new_fiber->stack_base );
210         else
211             siglongjmp( new_fiber->jmpbuf, 1 );
212     }
213 }
214 
215 /***********************************************************************
216  *           FlsAlloc   (KERNEL32.@)
217  */
218 DWORD WINAPI FlsAlloc( PFLS_CALLBACK_FUNCTION callback )
219 {
220     DWORD index;
221     PEB * const peb = NtCurrentTeb()->Peb;
222 
223     RtlAcquirePebLock();
224     if (!peb->FlsCallback &&
225         !(peb->FlsCallback = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
226                                         8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) )))
227     {
228         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
229         index = FLS_OUT_OF_INDEXES;
230     }
231     else
232     {
233         index = RtlFindClearBitsAndSet( peb->FlsBitmap, 1, 0 );
234         if (index != ~0U)
235         {
236             if (!NtCurrentTeb()->FlsSlots &&
237                 !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
238                                                         8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) )))
239             {
240                 RtlClearBits( peb->FlsBitmap, index, 1 );
241                 index = FLS_OUT_OF_INDEXES;
242                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
243             }
244             else
245             {
246                 NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */
247                 peb->FlsCallback[index] = callback;
248             }
249         }
250         else SetLastError( ERROR_NO_MORE_ITEMS );
251     }
252     RtlReleasePebLock();
253     return index;
254 }
255 
256 /***********************************************************************
257  *           FlsFree   (KERNEL32.@)
258  */
259 BOOL WINAPI FlsFree( DWORD index )
260 {
261     BOOL ret;
262 
263     RtlAcquirePebLock();
264     ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
265     if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 );
266     if (ret)
267     {
268         /* FIXME: call Fls callback */
269         /* FIXME: add equivalent of ThreadZeroTlsCell here */
270         if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0;
271     }
272     else SetLastError( ERROR_INVALID_PARAMETER );
273     RtlReleasePebLock();
274     return TRUE;
275 }
276 
277 /***********************************************************************
278  *           FlsGetValue   (KERNEL32.@)
279  */
280 PVOID WINAPI FlsGetValue( DWORD index )
281 {
282     if (index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) || !NtCurrentTeb()->FlsSlots)
283     {
284         SetLastError( ERROR_INVALID_PARAMETER );
285         return NULL;
286     }
287     SetLastError( ERROR_SUCCESS );
288     return NtCurrentTeb()->FlsSlots[index];
289 }
290 
291 /***********************************************************************
292  *           FlsSetValue   (KERNEL32.@)
293  */
294 BOOL WINAPI FlsSetValue( DWORD index, PVOID data )
295 {
296     if (index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits))
297     {
298         SetLastError( ERROR_INVALID_PARAMETER );
299         return FALSE;
300     }
301     if (!NtCurrentTeb()->FlsSlots &&
302         !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
303                                         8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) )))
304     {
305         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
306         return FALSE;
307     }
308     NtCurrentTeb()->FlsSlots[index] = data;
309     return TRUE;
310 }
311 
312 /***********************************************************************
313  *           IsThreadAFiber   (KERNEL32.@)
314  */
315 BOOL WINAPI IsThreadAFiber(void)
316 {
317     return NtCurrentTeb()->Tib.u.FiberData != NULL;
318 }
319 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.