/* $Id: oslibthread.cpp,v 1.1 2003-03-27 14:00:53 sandervl Exp $ */ /* * Wrappers for OS/2 Dos* API (Thread) * * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl) * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no) * * Project Odin Software License can be found in LICENSE.TXT * */ /******************************************************************************* * Header Files * *******************************************************************************/ #define INCL_BASE #define INCL_DOSEXCEPTIONS #define INCL_DOSMEMMGR #define INCL_DOSPROCESS #define INCL_DOSFILEMGR #define INCL_DOSERRORS #define INCL_DOSDEVIOCTL #define INCL_DOSDEVICES #define INCL_NPIPES #include //Odin32 OS/2 api wrappers #include #include #include #include #include #include #include #include "oslibdos.h" #include "oslibthread.h" #include "exceptions.h" #define DBG_LOCALLOG DBG_oslibthread #include "dbglocal.h" //****************************************************************************** //****************************************************************************** DWORD OSLibDosSetPriority(ULONG tid, int priority) { DWORD ret, os2priorityclass; LONG os2prioritydelta; APIRET rc; switch(priority) { case THREAD_PRIORITY_IDLE_W: os2priorityclass = PRTYC_IDLETIME; os2prioritydelta = 0; break; case THREAD_PRIORITY_LOWEST_W: os2priorityclass = PRTYC_REGULAR; os2prioritydelta = PRTYD_MINIMUM; break; case THREAD_PRIORITY_BELOW_NORMAL_W: os2priorityclass = PRTYC_REGULAR; os2prioritydelta = -15; break; case THREAD_PRIORITY_NORMAL_W: os2priorityclass = PRTYC_REGULAR; os2prioritydelta = 0; break; case THREAD_PRIORITY_ABOVE_NORMAL_W: os2priorityclass = PRTYC_REGULAR; os2prioritydelta = 15; break; case THREAD_PRIORITY_HIGHEST_W: os2priorityclass = PRTYC_REGULAR; os2prioritydelta = PRTYD_MAXIMUM; break; case THREAD_PRIORITY_TIME_CRITICAL_W: //NOTE: There is code relying on the fact that win32 threads can never // have the maximum priority available in OS/2!! // (e.g. SetThreadContext) dprintf(("PRTYC_TIMECRITICAL!!")); os2priorityclass = PRTYC_TIMECRITICAL; os2prioritydelta = 0; break; default: dprintf(("!WARNING!: Invalid priority!!")); SetLastError(ERROR_INVALID_PARAMETER_W); return ERROR_INVALID_PARAMETER_W; } rc = DosSetPriority(PRTYS_THREAD, os2priorityclass, os2prioritydelta, tid); ret = error2WinError(rc, ERROR_INVALID_PARAMETER); SetLastError(ret); return ret; } //****************************************************************************** //Useful to temporarily boost the priority to max to ensure it's scheduled first //Windows threads never receive such a high priority (time critical, delta 0 = max) //****************************************************************************** void OSLibDosSetMaxPriority(ULONG tid) { APIRET rc; dprintf(("OSLibDosSetMaxPriority for %x", tid)); rc = DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, tid); if(rc != NO_ERROR) { DebugInt3(); } } //****************************************************************************** //****************************************************************************** void OSLibDosExitThread(ULONG retcode) { DosExit(EXIT_THREAD, retcode); } //****************************************************************************** //****************************************************************************** BOOL OSLibQueryThreadContext(ULONG ulThreadId, ULONG teb_sel, CONTEXT *lpContext) { CONTEXTRECORD ctxrec; APIRET rc; int nrtries = 0; tryagain: rc = DosQueryThreadContext(ulThreadId, CONTEXT_FULL, &ctxrec); if(rc != NO_ERROR) { dprintf(("ERROR: DosQueryThreadContext failed with rc %d!!", rc)); //testestest if((rc == ERROR_NOT_FROZEN || rc == ERROR_INVALID_THREADID) && ++nrtries < 5) { DosSleep(50); goto tryagain; } DebugInt3(); SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER)); return FALSE; } if(lpContext->ContextFlags & WINCONTEXT_CONTROL) { lpContext->Ebp = ctxrec.ctx_RegEbp; lpContext->Eip = ctxrec.ctx_RegEip; lpContext->SegCs = ctxrec.ctx_SegCs; lpContext->EFlags = ctxrec.ctx_EFlags; lpContext->Esp = ctxrec.ctx_RegEsp; lpContext->SegSs = ctxrec.ctx_SegSs; } if(lpContext->ContextFlags & WINCONTEXT_INTEGER) { lpContext->Edi = ctxrec.ctx_RegEdi; lpContext->Esi = ctxrec.ctx_RegEsi; lpContext->Ebx = ctxrec.ctx_RegEbx; lpContext->Edx = ctxrec.ctx_RegEdx; lpContext->Ecx = ctxrec.ctx_RegEcx; lpContext->Eax = ctxrec.ctx_RegEax; } if(lpContext->ContextFlags & WINCONTEXT_SEGMENTS) { lpContext->SegGs = ctxrec.ctx_SegGs; // This resets FS to 0x150B - we DON'T want that!! // lpContext->SegFs = ctxrec.ctx_SegFs; lpContext->SegFs = teb_sel; lpContext->SegEs = ctxrec.ctx_SegEs; lpContext->SegDs = ctxrec.ctx_SegDs; } if(lpContext->ContextFlags & WINCONTEXT_FLOATING_POINT) { //TODO: First 7 dwords the same? memcpy(&lpContext->FloatSave, ctxrec.ctx_env, sizeof(ctxrec.ctx_env)); memcpy(&lpContext->FloatSave.RegisterArea, ctxrec.ctx_stack, sizeof(ctxrec.ctx_stack)); } SetLastError(ERROR_SUCCESS_W); return TRUE; } //****************************************************************************** //****************************************************************************** void OSLibDisableThreadSwitching() { DosEnterCritSec(); } //****************************************************************************** //****************************************************************************** void OSLibEnableThreadSwitching() { DosExitCritSec(); } //****************************************************************************** //******************************************************************************