Implemented the Fiber* functions (with the help of Huw Davies).

oldstable
Alexandre Julliard 2002-12-17 21:06:25 +00:00
parent ea118ecb50
commit 9e8e5ff71d
6 changed files with 213 additions and 8 deletions

View File

@ -182,7 +182,9 @@
@ stdcall ConnectNamedPipe(long ptr) ConnectNamedPipe
@ stdcall ContinueDebugEvent(long long long) ContinueDebugEvent
@ stdcall ConvertDefaultLocale (long) ConvertDefaultLocale
@ stub ConvertThreadToFiber
@ stdcall ConvertFiberToThread() ConvertFiberToThread
@ stdcall ConvertThreadToFiber(ptr) ConvertThreadToFiber
@ stdcall ConvertThreadToFiberEx(ptr long) ConvertThreadToFiberEx
@ stdcall ConvertToGlobalHandle(long) ConvertToGlobalHandle
@ stdcall CopyFileA(str str long) CopyFileA
@ stdcall CopyFileW(wstr wstr long) CopyFileW
@ -983,10 +985,11 @@
@ stdcall CancelWaitableTimer(long) CancelWaitableTimer
@ stdcall CopyFileExA (str str ptr ptr ptr long) CopyFileExA
@ stdcall CopyFileExW (wstr wstr ptr ptr ptr long) CopyFileExW
@ stub CreateFiber
@ stdcall CreateFiber(long ptr ptr) CreateFiber
@ stdcall CreateFiberEx(long long long ptr ptr) CreateFiberEx
@ stdcall CreateWaitableTimerA(ptr long str) CreateWaitableTimerA
@ stdcall CreateWaitableTimerW(ptr long wstr) CreateWaitableTimerW
@ stub DeleteFiber
@ stdcall DeleteFiber(ptr) DeleteFiber
@ stub DuplicateConsoleHandle
@ stdcall FindFirstFileExA(str long ptr long ptr long)FindFirstFileExA
@ stdcall FindFirstFileExW(wstr long ptr long ptr long)FindFirstFileExW
@ -1018,7 +1021,7 @@
@ stdcall SetThreadPriorityBoost(long long) SetThreadPriorityBoost
@ stdcall SetWaitableTimer(long ptr long ptr ptr long) SetWaitableTimer
@ stub SignalObjectAndWait
@ stub SwitchToFiber
@ stdcall SwitchToFiber(ptr) SwitchToFiber
@ stdcall SwitchToThread() SwitchToThread
@ stdcall TryEnterCriticalSection(ptr) ntdll.RtlTryEnterCriticalSection
@ stdcall VirtualAllocEx(long ptr long long long) VirtualAllocEx

View File

@ -59,6 +59,7 @@ C_SRCS = \
$(TOPOBJDIR)/relay32/snoop.c \
$(TOPOBJDIR)/scheduler/client.c \
$(TOPOBJDIR)/scheduler/critsection.c \
$(TOPOBJDIR)/scheduler/fiber.c \
$(TOPOBJDIR)/scheduler/handle.c \
$(TOPOBJDIR)/scheduler/pipe.c \
$(TOPOBJDIR)/scheduler/process.c \

View File

@ -29,6 +29,7 @@ struct __EXCEPTION_FRAME;
struct _SECURITY_ATTRIBUTES;
struct tagSYSLEVEL;
struct server_buffer_info;
struct fiber_data;
/* Thread exception block
@ -52,7 +53,7 @@ typedef struct _TEB
void *stack_low; /* 12- 08 Stack low-water mark */
HTASK16 htask16; /* 1-- 0c Win16 task handle */
WORD stack_sel; /* 1-- 0e 16-bit stack selector */
DWORD selman_list; /* 1-n 10 Selector manager list */
struct fiber_data *fiber; /* -2- 10 Current fiber data (Win95: selector manager list) */
DWORD user_ptr; /* 12n 14 User pointer */
/* end of NT_TIB */
struct _TEB *self; /* 12- 18 Pointer to this structure */
@ -73,8 +74,8 @@ typedef struct _TEB
void (*startup)(void); /* --3 48 Thread startup routine */
int thread_errno; /* --3 4c Per-thread errno (was: ring0_thread) */
int thread_h_errno; /* --3 50 Per-thread h_errno (was: ptr to tdbx structure) */
void *stack_base; /* 1-- 54 Base of the stack */
void *signal_stack; /* --3 58 Signal stack (was: exit_stack) */
void *signal_stack; /* --3 54 Signal stack (was: stack_base) */
void *exit_stack; /* 1-n 58 Exit stack */
void *emu_data; /* --n 5c Related to 80387 emulation */
DWORD last_error; /* 1-- 60 Last error code */
HANDLE debug_cb; /* 1-n 64 Debugger context block */
@ -121,7 +122,7 @@ typedef struct _TEB
DWORD pad6[624]; /* --n 238 */
UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */
USHORT StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
DWORD pad7; /* --n e0c */
void *stack_base; /* -2- e0c Base of the stack */
LPVOID tls_array[64]; /* -2- e10 Thread local storage */
DWORD pad8[3]; /* --n f10 */
PVOID ReservedForNtRpc; /* -2- f1c used by rpcrt4 */

View File

@ -1178,9 +1178,14 @@ BOOL WINAPI CopyFileExW(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPB
#define CopyFileEx WINELIB_NAME_AW(CopyFileEx)
BOOL WINAPI CopySid(DWORD,PSID,PSID);
INT WINAPI CompareFileTime(const FILETIME*,const FILETIME*);
BOOL WINAPI ConvertFiberToThread(void);
LPVOID WINAPI ConvertThreadToFiber(LPVOID);
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID,DWORD);
HANDLE WINAPI CreateEventA(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR);
HANDLE WINAPI CreateEventW(LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCWSTR);
#define CreateEvent WINELIB_NAME_AW(CreateEvent)
LPVOID WINAPI CreateFiber(SIZE_T,LPFIBER_START_ROUTINE,LPVOID);
LPVOID WINAPI CreateFiberEx(SIZE_T,SIZE_T,DWORD,LPFIBER_START_ROUTINE,LPVOID);
HANDLE WINAPI CreateFileA(LPCSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);
HANDLE WINAPI CreateFileW(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);
#define CreateFile WINELIB_NAME_AW(CreateFile)
@ -1217,6 +1222,7 @@ BOOL WINAPI DebugActiveProcessStop(DWORD);
void WINAPI DebugBreak(void);
BOOL WINAPI DebugBreakProcess(HANDLE);
BOOL WINAPI DebugSetProcessKillOnExit(BOOL);
void WINAPI DeleteFiber(LPVOID);
BOOL WINAPI DeleteTimerQueueEx(HANDLE,HANDLE);
BOOL WINAPI DeleteTimerQueueTimer(HANDLE,HANDLE,HANDLE);
BOOL WINAPI DeregisterEventSource(HANDLE);
@ -1501,6 +1507,7 @@ DWORD WINAPI SignalObjectAndWait(HANDLE,HANDLE,DWORD,BOOL);
VOID WINAPI Sleep(DWORD);
DWORD WINAPI SleepEx(DWORD,BOOL);
DWORD WINAPI SuspendThread(HANDLE);
void WINAPI SwitchToFiber(LPVOID);
BOOL WINAPI SwitchToThread(void);
BOOL WINAPI SystemTimeToFileTime(const SYSTEMTIME*,LPFILETIME);
DWORD WINAPI TlsAlloc(void);

View File

@ -1676,6 +1676,12 @@ extern inline struct _TEB * WINAPI NtCurrentTeb(void)
extern struct _TEB * WINAPI NtCurrentTeb(void);
#endif
#ifdef NONAMELESSUNION
#define GetCurrentFiber() (((NT_TIB *)NtCurrentTeb())->u.FiberData)
#else
#define GetCurrentFiber() (((NT_TIB *)NtCurrentTeb())->FiberData)
#endif
#define GetFiberData() (*(void **)GetCurrentFiber())
/*
* File formats definitions

187
scheduler/fiber.c 100644
View File

@ -0,0 +1,187 @@
/*
* Fiber support
*
* Copyright 2002 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME:
* - proper handling of 16-bit stack and signal stack
*/
#include <setjmp.h>
#include "winbase.h"
#include "winerror.h"
#include "thread.h"
struct fiber_data
{
LPVOID param; /* 00 fiber param */
void *except; /* 04 saved exception handlers list */
void *stack_top; /* 08 top of fiber stack */
void *stack_low; /* 0c fiber stack low-water mark */
void *stack_base; /* 10 base of the fiber stack */
jmp_buf jmpbuf; /* 14 setjmp buffer (on Windows: CONTEXT) */
DWORD flags; /* fiber flags */
LPFIBER_START_ROUTINE start; /* start routine */
};
/* call the fiber initial function once we have switched stack */
static void start_fiber(void)
{
struct fiber_data *fiber = NtCurrentTeb()->fiber;
LPFIBER_START_ROUTINE start = fiber->start;
fiber->start = NULL;
start( fiber->param );
ExitThread( 1 );
}
/***********************************************************************
* CreateFiber (KERNEL32.@)
*/
LPVOID WINAPI CreateFiber( SIZE_T stack, LPFIBER_START_ROUTINE start, LPVOID param )
{
return CreateFiberEx( stack, 0, 0, start, param );
}
/***********************************************************************
* CreateFiberEx (KERNEL32.@)
*/
LPVOID WINAPI CreateFiberEx( SIZE_T stack_commit, SIZE_T stack_reserve, DWORD flags,
LPFIBER_START_ROUTINE start, LPVOID param )
{
struct fiber_data *fiber;
if (!(fiber = HeapAlloc( GetProcessHeap(), 0, sizeof(*fiber) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
/* FIXME: should use the thread stack allocation routines here */
if (!stack_reserve) stack_reserve = 1024*1024;
if(!(fiber->stack_base = VirtualAlloc( 0, stack_reserve, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
{
HeapFree( GetProcessHeap(), 0, fiber );
return NULL;
}
fiber->stack_top = (char *)fiber->stack_base + stack_reserve;
fiber->stack_low = fiber->stack_base;
fiber->param = param;
fiber->except = (void *)-1;
fiber->start = start;
fiber->flags = flags;
return fiber;
}
/***********************************************************************
* DeleteFiber (KERNEL32.@)
*/
void WINAPI DeleteFiber( LPVOID fiber_ptr )
{
struct fiber_data *fiber = fiber_ptr;
if (!fiber) return;
if (fiber == NtCurrentTeb()->fiber)
{
HeapFree( GetProcessHeap(), 0, fiber );
ExitThread(1);
}
VirtualFree( fiber->stack_base, 0, MEM_RELEASE );
HeapFree( GetProcessHeap(), 0, fiber );
}
/***********************************************************************
* ConvertThreadToFiber (KERNEL32.@)
*/
LPVOID WINAPI ConvertThreadToFiber( LPVOID param )
{
return ConvertThreadToFiberEx( param, 0 );
}
/***********************************************************************
* ConvertThreadToFiberEx (KERNEL32.@)
*/
LPVOID WINAPI ConvertThreadToFiberEx( LPVOID param, DWORD flags )
{
struct fiber_data *fiber;
if (!(fiber = HeapAlloc( GetProcessHeap(), 0, sizeof(*fiber) )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
fiber->param = param;
fiber->except = NtCurrentTeb()->except;
fiber->stack_top = NtCurrentTeb()->stack_top;
fiber->stack_low = NtCurrentTeb()->stack_low;
fiber->stack_base = NtCurrentTeb()->stack_base;
fiber->start = NULL;
fiber->flags = flags;
NtCurrentTeb()->fiber = fiber;
return fiber;
}
/***********************************************************************
* ConvertFiberToThread (KERNEL32.@)
*/
BOOL WINAPI ConvertFiberToThread(void)
{
struct fiber_data *fiber = NtCurrentTeb()->fiber;
if (fiber)
{
NtCurrentTeb()->fiber = NULL;
HeapFree( GetProcessHeap(), 0, fiber );
}
return TRUE;
}
/***********************************************************************
* SwitchToFiber (KERNEL32.@)
*/
void WINAPI SwitchToFiber( LPVOID fiber )
{
struct fiber_data *new_fiber = fiber;
struct fiber_data *current_fiber = NtCurrentTeb()->fiber;
current_fiber->except = NtCurrentTeb()->except;
current_fiber->stack_low = NtCurrentTeb()->stack_low;
/* stack_base and stack_top never change */
/* FIXME: should save floating point context if requested in fiber->flags */
if (!setjmp( current_fiber->jmpbuf ))
{
NtCurrentTeb()->fiber = new_fiber;
NtCurrentTeb()->except = new_fiber->except;
NtCurrentTeb()->stack_top = new_fiber->stack_top;
NtCurrentTeb()->stack_low = new_fiber->stack_low;
NtCurrentTeb()->stack_base = new_fiber->stack_base;
if (new_fiber->start) /* first time */
SYSDEPS_SwitchToThreadStack( start_fiber );
else
longjmp( new_fiber->jmpbuf, 1 );
}
}