/* Find a thread record given a thread id. If GET_CONTEXT is set then also retrieve the context for this thread. */ static thread_info * thread_rec (DWORD id, int get_context) { struct thread_info *thread; thread_info *th; thread = (struct thread_info *) find_inferior_id (&all_threads, id); if (thread == NULL) return NULL; th = inferior_target_data (thread); if (!th->suspend_count && get_context) { if (get_context > 0 && id != current_event.dwThreadId) th->suspend_count = SuspendThread (th->h) + 1; else if (get_context < 0) th->suspend_count = -1; th->context.ContextFlags = CONTEXT_DEBUGGER_DR; GetThreadContext (th->h, &th->context); if (id == current_event.dwThreadId) { /* Copy dr values from that thread. */ dr[0] = th->context.Dr0; dr[1] = th->context.Dr1; dr[2] = th->context.Dr2; dr[3] = th->context.Dr3; dr[6] = th->context.Dr6; dr[7] = th->context.Dr7; } } return th; }
static DWORD WINAPI profiler_thread_entry(LPVOID lpParameter) { HANDLE mainThread = (HANDLE)lpParameter; CONTEXT context; /* loop until done */ memset(&context, 0, sizeof(context)); while (!profiler_thread_exit) { /* pause the main thread and get its context */ SuspendThread(mainThread); context.ContextFlags = CONTEXT_FULL; GetThreadContext(mainThread, &context); ResumeThread(mainThread); /* add to the bucket */ increment_bucket(context.Eip); /* sleep */ Sleep(1); } return 0; }
static gboolean gst_directsound_ring_buffer_pause (GstRingBuffer * buf) { HRESULT hr = S_OK; GstDirectSoundRingBuffer * dsoundbuffer; dsoundbuffer = GST_DIRECTSOUND_RING_BUFFER (buf); GST_DEBUG ("Pausing RingBuffer"); GST_DSOUND_LOCK (dsoundbuffer); if (dsoundbuffer->pDSB8) { hr = IDirectSoundBuffer8_Stop (dsoundbuffer->pDSB8); } if (G_LIKELY (!dsoundbuffer->suspended)) { if (G_UNLIKELY(SuspendThread (dsoundbuffer->hThread) == -1)) GST_WARNING ("gst_directsound_ring_buffer_pause: SuspendThread failed."); else dsoundbuffer->suspended = TRUE; } GST_DSOUND_UNLOCK (dsoundbuffer); /* in the unlikely event that a device was reconfigured, we can consider * ourselves stopped even though the stop call failed */ if (G_UNLIKELY (FAILED(hr)) && G_UNLIKELY(hr != DIRECTSOUND_ERROR_DEVICE_RECONFIGURED) && G_UNLIKELY(hr != DIRECTSOUND_ERROR_DEVICE_NO_DRIVER)) { GST_WARNING ("gst_directsound_ring_buffer_pause: IDirectSoundBuffer8_Stop, hr = %X", (unsigned int) hr); return FALSE; } return TRUE; }
DWORD WINAPI stream_run(void * data) { SoundThread * me = (SoundThread *) data; while(me->running) { if(me->sound) { Sound * sound = me->sound; ALuint uiSource; ALint iState = AL_PLAYING; ALuint uiBuffers[1]; alGenBuffers(1, uiBuffers); alGenSources(1, &uiSource); alBufferData(uiBuffers[0], sound->format, sound->data, sound->size, sound->freq); assert(AL_NO_ERROR == alGetError()); alSourceQueueBuffers(uiSource, 1, &uiBuffers[0]); alSourcef(uiSource, AL_GAIN, sound->volume); alSourcePlay(uiSource); while(iState == AL_PLAYING) { Sleep(16); alGetSourcei(uiSource, AL_SOURCE_STATE, &iState); } alSourceStop(uiSource); alSourcei(uiSource, AL_BUFFER, 0); alDeleteSources(1, &uiSource); alDeleteBuffers(1, uiBuffers); me->occupied = false; me->sound = 0; } if(me->running) SuspendThread(me->handle); } return 0; }
static void prvProcessSimulatedInterrupts( void ) { unsigned long ulSwitchRequired, i; xThreadState *pxThreadState; void *pvObjectList[ 2 ]; /* Going to block on the mutex that ensured exclusive access to the simulated interrupt objects, and the event that signals that a simulated interrupt should be processed. */ pvObjectList[ 0 ] = pvInterruptEventMutex; pvObjectList[ 1 ] = pvInterruptEvent; for(;;) { WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE ); /* Used to indicate whether the simulated interrupt processing has necessitated a context switch to another task/thread. */ ulSwitchRequired = pdFALSE; /* For each interrupt we are interested in processing, each of which is represented by a bit in the 32bit ulPendingInterrupts variable. */ for( i = 0; i < portMAX_INTERRUPTS; i++ ) { /* Is the simulated interrupt pending? */ if( ulPendingInterrupts & ( 1UL << i ) ) { /* Is a handler installed? */ if( ulIsrHandler[ i ] != NULL ) { /* Run the actual handler. */ if( ulIsrHandler[ i ]() != pdFALSE ) { ulSwitchRequired |= ( 1 << i ); } } /* Clear the interrupt pending bit. */ ulPendingInterrupts &= ~( 1UL << i ); } } if( ulSwitchRequired != pdFALSE ) { void *pvOldCurrentTCB; pvOldCurrentTCB = pxCurrentTCB; /* Select the next task to run. */ vTaskSwitchContext(); /* If the task selected to enter the running state is not the task that is already in the running state. */ if( pvOldCurrentTCB != pxCurrentTCB ) { /* Suspend the old thread. */ pxThreadState = ( xThreadState *) *( ( unsigned long * ) pvOldCurrentTCB ); if( ( ulSwitchRequired & ( 1 << portINTERRUPT_DELETE_THREAD ) ) != pdFALSE ) { TerminateThread( pxThreadState->pvThread, 0 ); } else { SuspendThread( pxThreadState->pvThread ); } /* Obtain the state of the task now selected to enter the Running state. */ pxThreadState = ( xThreadState * ) ( *( unsigned long *) pxCurrentTCB ); ResumeThread( pxThreadState->pvThread ); } } ReleaseMutex( pvInterruptEventMutex ); } }
/* * ThreadCtlProc */ BOOL CALLBACK ThreadCtlProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { WORD cmd; ThreadCtlInfo *info; LRESULT index; char buf[200]; DWORD threadid; ThreadNode *thread; ProcNode *process; DWORD susp_cnt; DWORD rc; char *action; info = (ThreadCtlInfo *)GET_DLGDATA( hwnd ); switch( msg ) { case WM_INITDIALOG: info = MemAlloc( sizeof( ThreadCtlInfo ) ); if( !GetProcessInfo( lparam, &info->procinfo ) ) { RCsprintf( buf, STR_CANT_GET_PROC_INFO, info->procid ); MessageBox( hwnd, buf, AppName, MB_OK | MB_ICONEXCLAMATION ); SendMessage( hwnd, WM_CLOSE, 0, 0 ); } info->procid = lparam; ThreadDlg = hwnd; SET_DLGDATA( hwnd, info ); fillThreadCtl( hwnd, &info->procinfo, buf ); RCsprintf( buf, STR_THREAD_4_PROC_X, lparam ); SetDlgItemText( hwnd, THREAD_PROC_NAME, buf ); sprintf( buf, "(%s)", info->procinfo.name ); SetDlgItemText( hwnd, THREAD_PROC_PATH, buf ); SendDlgItemMessage( hwnd, THREAD_LIST, LB_SETCURSEL, 0, 0L ); index = SendDlgItemMessage( hwnd, THREAD_LIST, LB_GETCURSEL, 0, 0L ); if( index != LB_ERR ) { enableChoices( hwnd, TRUE ); } fillThreadInfo( hwnd, &info->procinfo ); break; case WM_COMMAND: cmd = LOWORD( wparam ); if( cmd == THREAD_SUSPEND || cmd == THREAD_RESUME || cmd == THREAD_KILL || cmd == THREAD_SET_PRIORITY ) { index = SendDlgItemMessage( hwnd, THREAD_LIST, LB_GETCURSEL, 0, 0L ); if( index == LB_ERR ) { RCMessageBox( hwnd, STR_NO_SELECTED_THREAD, AppName, MB_OK | MB_ICONEXCLAMATION ); break; } SendDlgItemMessage( hwnd, THREAD_LIST, LB_GETTEXT, (WPARAM)index, (LPARAM)(LPSTR)buf ); threadid = getThreadId( buf ); process = FindProcess( info->procinfo.pid ); thread = FindThread( process, threadid ); } switch( cmd ) { case IDOK: SendMessage( hwnd, WM_CLOSE, 0, 0L ); break; case THREAD_REFRESH: RefreshInfo(); if( GetProcessInfo( info->procid, &info->procinfo ) ) { fillThreadCtl( hwnd, &info->procinfo, buf ); fillThreadInfo( hwnd, &info->procinfo ); } else { action = AllocRCString( STR_REFRESH ); RCMessageBox( hwnd, STR_CANT_REFRESH_THRD, action, MB_OK | MB_ICONEXCLAMATION ); FreeRCString( action ); } break; case THREAD_SUSPEND: action = AllocRCString( STR_THREAD_SUSPEND ); if( thread == NULL ) { RCsprintf( buf, STR_CANT_GET_HDL_4_THD_X, threadid ); MessageBox( hwnd, buf, action, MB_OK | MB_ICONEXCLAMATION ); } else { susp_cnt = SuspendThread( thread->threadhdl ); if( susp_cnt == -1 ) { RCsprintf( buf, STR_CANT_SUSPEND_THRD_X, threadid ); MessageBox( hwnd, buf, action, MB_ICONQUESTION | MB_OK ); } else if( susp_cnt > 0 ) { RCsprintf( buf, STR_THREAD_ALREADY_SUSP, threadid, susp_cnt ); index = MessageBox( hwnd, buf, action, MB_ICONQUESTION | MB_YESNO ); if( index == IDNO ) { ResumeThread( thread->threadhdl ); } } SendMessage( hwnd, WM_COMMAND, THREAD_REFRESH, 0L ); } FreeRCString( action ); break; case THREAD_RESUME: action = AllocRCString( STR_RESUME ); if( thread == NULL ) { RCsprintf( buf, STR_THREAD_NOT_RESUMED , threadid ); MessageBox( hwnd, buf, action, MB_OK | MB_ICONEXCLAMATION ); } else { susp_cnt = ResumeThread( thread->threadhdl ); if( susp_cnt == -1 ) { RCsprintf( buf, STR_CANT_RESUME_THRD_X, threadid ); MessageBox( hwnd, buf, action, MB_ICONEXCLAMATION | MB_OK ); } else if( susp_cnt == 0 ) { RCsprintf( buf, STR_THRD_IS_NOT_SUSP, threadid ); MessageBox( hwnd, buf, action, MB_ICONEXCLAMATION | MB_OK ); } else if( susp_cnt > 1 ) { RCsprintf( buf, STR_SUSP_COUNT_DECREMENTED, threadid, susp_cnt ); MessageBox( hwnd, buf, action, MB_ICONEXCLAMATION | MB_OK ); } SendMessage( hwnd, WM_COMMAND, THREAD_REFRESH, 0L ); } FreeRCString( action ); break; case THREAD_KILL: action = AllocRCString( STR_KILL ); if( thread == NULL ) { RCsprintf( buf, STR_THRD_NOT_TERMINATED, threadid ); MessageBox( hwnd, buf, action, MB_OK | MB_ICONEXCLAMATION ); } else if( GetRetCode( hwnd, RETCD_THREAD, thread->threadid, &rc ) ) { if( !TerminateThread( thread->threadhdl, rc ) ) { RCsprintf( buf, STR_CANT_KILL_THRD_X, threadid ); MessageBox( hwnd, buf, action, MB_OK | MB_ICONEXCLAMATION ); } SendMessage( hwnd, WM_COMMAND, THREAD_REFRESH, 0L ); } FreeRCString( action ); break; case THREAD_SET_PRIORITY: // { // ThreadPriorityInfo prinfo; // // if( thread == NULL ) { // sprintf( buf, "Unable to get a handle for thread %08X.\n", // threadid ); // MessageBox( hwnd, buf, "Set Priority", // MB_OK | MB_ICONEXCLAMATION ); // } else { // prinfo.procid = info->procid; // prinfo.thread = thread; // prinfo.priority = GetThreadPriority( thread->threadhdl ); // prinfo.procinfo = &info->procinfo; // DialogBoxParam( Instance, "THREAD_PRIORITY_DLG", hwnd, // ThreadPriorityDlgProc, (DWORD)&prinfo ); // fillThreadInfo( hwnd, &info->procinfo ); // } // } // break; case THREAD_LIST: if( HIWORD( wparam ) == LBN_SELCHANGE ) { fillThreadInfo( hwnd, &info->procinfo ); } break; } break; case DR_TASK_LIST_CHANGE: /* make sure this process still exists */ //here if( FindProcess( info->procid ) == NULL ) { //here SendDlgItemMessage( hwnd, THREAD_LIST, LB_RESETCONTENT, 0, 0L ); //here enableChoices( hwnd, FALSE ); //here info->proc = NULL; //here } else { //here fillThreadCtl( hwnd, info->proc, buf ); //here } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; case WM_DESTROY: MemFree( info ); ThreadDlg = NULL; break; default: return( FALSE ); } return( TRUE ); }
BOOL WINAPI SSQ_SetLogStatus(BOOL status,USHORT port) { static LPADDRINFO response; static char hostname[64]; if(status==log_status||HIWORD(Callback)==0||ssq_is_initialized==FALSE) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,0); return FALSE; } else if(GetExitCodeThread(handle_log_thread,&exit_code_log_thread)==FALSE) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,(DWORD)GetExitCodeThread); return FALSE; } else if(exit_code_log_thread!=STILL_ACTIVE) { handle_log_thread = CreateThread(0,0,SSQ_LogThread,0,CREATE_SUSPENDED,&identifier_log_thread); if(handle_log_thread==0) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,(DWORD)CreateThread); return FALSE; } } if(status==TRUE) { if(gethostname(hostname,sizeof(hostname))==SOCKET_ERROR) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,1,1,(DWORD)gethostname); return FALSE; } else if(getaddrinfo(hostname,0,0,&response)!=0) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,1,1,(DWORD)getaddrinfo); return FALSE; } else if(closesocket(ssq_socket[SSQ_UDP_LOG])==SOCKET_ERROR) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,1,1,(DWORD)closesocket); return FALSE; } ssq_socket[SSQ_UDP_LOG] = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if(ssq_socket[SSQ_UDP_LOG]==INVALID_SOCKET) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,1,1,(DWORD)socket); return FALSE; } ((PSOCKADDR_IN)response->ai_addr)->sin_port = htons(port); if(bind(ssq_socket[SSQ_UDP_LOG],response->ai_addr,sizeof(*response->ai_addr))==SOCKET_ERROR) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,1,1,(DWORD)bind); return FALSE; } freeaddrinfo(response); if(ResumeThread(handle_log_thread)==0xFFFFFFFF) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,(DWORD)ResumeThread); return FALSE; } log_status = TRUE; } else if(status==FALSE) { if(SuspendThread(handle_log_thread)==0xFFFFFFFF) { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,(DWORD)SuspendThread); return FALSE; } log_status = FALSE; } else { SSQ_OutputDebugString(EXTERNAL_SSQ_SET_LOG_STATUS,0,1,0); return FALSE; } return TRUE; }
void CThread::Suspend() { SuspendThread(m_hThread); }
/** Print out a stacktrace. */ static void Stacktrace(const char *threadName, LPEXCEPTION_POINTERS e, HANDLE hThread = INVALID_HANDLE_VALUE) { PIMAGEHLP_SYMBOL pSym; STACKFRAME sf; HANDLE process, thread; DWORD dwModBase, Disp, dwModAddrToPrint; BOOL more = FALSE; int count = 0; char modname[MAX_PATH]; process = GetCurrentProcess(); if(threadName) PRINT("Stacktrace (%s):", threadName); else PRINT("Stacktrace:"); bool suspended = false; CONTEXT c; if (e) { c = *e->ContextRecord; thread = GetCurrentThread(); } else { SuspendThread(hThread); suspended = true; memset(&c, 0, sizeof(CONTEXT)); c.ContextFlags = CONTEXT_FULL; // FIXME: This does not work if you want to dump the current thread's stack if (!GetThreadContext(hThread, &c)) { ResumeThread(hThread); return; } thread = hThread; } ZeroMemory(&sf, sizeof(sf)); sf.AddrPC.Offset = c.Eip; sf.AddrStack.Offset = c.Esp; sf.AddrFrame.Offset = c.Ebp; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; // use globalalloc to reduce risk for allocator related deadlock pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); char* printstrings = (char*)GlobalAlloc(GMEM_FIXED, 0); bool containsOglDll = false; while (true) { more = StackWalk( IMAGE_FILE_MACHINE_I386, // TODO: fix this for 64 bit windows? process, thread, &sf, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL ); if (!more || sf.AddrFrame.Offset == 0 || count > MAX_STACK_DEPTH) { break; } dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset); if (dwModBase) { GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH); } else { strcpy(modname, "Unknown"); } pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pSym->MaxNameLength = MAX_PATH; char* printstringsnew = (char*) GlobalAlloc(GMEM_FIXED, (count + 1) * BUFFER_SIZE); memcpy(printstringsnew, printstrings, count * BUFFER_SIZE); GlobalFree(printstrings); printstrings = printstringsnew; if (SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym)) { // This is the code path taken on VC if debugging syms are found. SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s(%s+%#0lx) [0x%08lX]", count, modname, pSym->Name, Disp, sf.AddrPC.Offset); } else { // This is the code path taken on MinGW, and VC if no debugging syms are found. if (strstr(modname, ".exe")) { // for the .exe, we need the absolute address dwModAddrToPrint = sf.AddrPC.Offset; } else { // for DLLs, we need the module-internal/relative address dwModAddrToPrint = sf.AddrPC.Offset - dwModBase; } SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s [0x%08lX]", count, modname, dwModAddrToPrint); } // OpenGL lib names (ATI): "atioglxx.dll" "atioglx2.dll" containsOglDll = containsOglDll || strstr(modname, "atiogl"); // OpenGL lib names (Nvidia): "nvoglnt.dll" "nvoglv32.dll" "nvoglv64.dll" (last one is a guess) containsOglDll = containsOglDll || strstr(modname, "nvogl"); // OpenGL lib names (Intel): "ig4dev32.dll" "ig4dev64.dll" containsOglDll = containsOglDll || strstr(modname, "ig4dev"); ++count; } if (suspended) { ResumeThread(hThread); } if (containsOglDll) { PRINT("This stack trace indicates a problem with your graphic card driver. " "Please try upgrading or downgrading it. " "Specifically recommended is the latest driver, and one that is as old as your graphic card. " "Make sure to use a driver removal utility, before installing other drivers."); } for (int i = 0; i < count; ++i) { PRINT("%s", printstrings + i * BUFFER_SIZE); } GlobalFree(printstrings); GlobalFree(pSym); }
DWORD PALAPI SuspenderThread() { HANDLE targetThread; DWORD ret; int i,j,idx,jdx; printf("[Suspender Thread] Starting\n"); while (!g_bDone) { jdx = rand()%2; for (j=0; j<2; j++, jdx++) { switch(jdx % 2) { case 0: { idx = rand() % g_lCurrentExecutingThreadCount; for (i=0; i < g_lCurrentExecutingThreadCount; i++) { targetThread = g_rghExecutingThread[idx]; if (NULL != targetThread) { ret = SuspendThread(targetThread); if (-1 != ret) { g_lSuspCount += 1; } else { g_lSuspFailCount += 1; } } idx = (idx+1) % g_lCurrentExecutingThreadCount; } break; } case 1: default: { idx = rand() % g_lPostingThreadCount; for (i=0; i < g_lPostingThreadCount; i++) { targetThread = g_rghPostingThread[idx]; if (NULL != targetThread) { ret = SuspendThread(targetThread); if (-1 != ret) { g_lSuspCount += 1; } else { g_lSuspFailCount += 1; } } idx = (idx+1) % g_lPostingThreadCount; } break; } } } Sleep(rand() % 100); jdx = rand() % 2; for (j=0; j<2; j++, jdx++) { switch(jdx % 2) { case 0: { idx = rand() % g_lCurrentExecutingThreadCount; for (i=0; i < g_lCurrentExecutingThreadCount; i++) { targetThread = g_rghExecutingThread[idx]; if (NULL != targetThread) { ret = ResumeThread(targetThread); if (-1 != ret) { g_lResumeCount += 1; } else { g_lResumeFailCount += 1; } } idx = (idx+1) % g_lCurrentExecutingThreadCount; } break; } case 1: default: { idx = rand() % g_lPostingThreadCount; for (i=0; i < g_lPostingThreadCount; i++) { targetThread = g_rghPostingThread[idx]; if (NULL != targetThread) { ret = ResumeThread(targetThread); if (-1 != ret) { g_lResumeCount += 1; } else { g_lResumeFailCount += 1; } } idx = (idx+1) % g_lPostingThreadCount; } break; } } } Sleep(rand() % 100); } printf("[Suspender Thread] Done\n"); return 0; }
void cThreadWrapper::Suspend() { m_dwThreadSuspendCount = SuspendThread(m_hThreadHandle); }
static void prvProcessSimulatedInterrupts( void ) { uint32_t ulSwitchRequired, i; xThreadState *pxThreadState; void *pvObjectList[ 2 ]; CONTEXT xContext; /* Going to block on the mutex that ensured exclusive access to the simulated interrupt objects, and the event that signals that a simulated interrupt should be processed. */ pvObjectList[ 0 ] = pvInterruptEventMutex; pvObjectList[ 1 ] = pvInterruptEvent; /* Create a pending tick to ensure the first task is started as soon as this thread pends. */ ulPendingInterrupts |= ( 1 << portINTERRUPT_TICK ); SetEvent( pvInterruptEvent ); xPortRunning = pdTRUE; for(;;) { WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE ); /* Used to indicate whether the simulated interrupt processing has necessitated a context switch to another task/thread. */ ulSwitchRequired = pdFALSE; /* For each interrupt we are interested in processing, each of which is represented by a bit in the 32bit ulPendingInterrupts variable. */ for( i = 0; i < portMAX_INTERRUPTS; i++ ) { /* Is the simulated interrupt pending? */ if( ulPendingInterrupts & ( 1UL << i ) ) { /* Is a handler installed? */ if( ulIsrHandler[ i ] != NULL ) { /* Run the actual handler. */ if( ulIsrHandler[ i ]() != pdFALSE ) { ulSwitchRequired |= ( 1 << i ); } } /* Clear the interrupt pending bit. */ ulPendingInterrupts &= ~( 1UL << i ); } } if( ulSwitchRequired != pdFALSE ) { void *pvOldCurrentTCB; pvOldCurrentTCB = pxCurrentTCB; /* Select the next task to run. */ vTaskSwitchContext(); /* If the task selected to enter the running state is not the task that is already in the running state. */ if( pvOldCurrentTCB != pxCurrentTCB ) { /* Suspend the old thread. */ pxThreadState = ( xThreadState *) *( ( size_t * ) pvOldCurrentTCB ); SuspendThread( pxThreadState->pvThread ); /* Ensure the thread is actually suspended by performing a synchronous operation that can only complete when the thread is actually suspended. The below code asks for dummy register data. */ xContext.ContextFlags = CONTEXT_INTEGER; ( void ) GetThreadContext( pxThreadState->pvThread, &xContext ); /* Obtain the state of the task now selected to enter the Running state. */ pxThreadState = ( xThreadState * ) ( *( size_t *) pxCurrentTCB ); ResumeThread( pxThreadState->pvThread ); } } ReleaseMutex( pvInterruptEventMutex ); } }
DWORD demoSuspendInjectResume(PCWSTR pszLibFile, DWORD dwProcessId) { void *stub; unsigned long threadID, oldIP, oldprot; HANDLE hThread; CONTEXT ctx; DWORD stubLen = sizeof(sc); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == NULL) { wprintf(L"[-] Error: Could not open process for PID (%d).\n", dwProcessId); return(1); } DWORD LoadLibraryAddress = (DWORD)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); if (LoadLibraryAddress == NULL) { wprintf(L"[-] Error: Could not find LoadLibraryA function inside kernel32.dll library.\n"); exit(1); } SIZE_T dwSize = (wcslen(pszLibFile) + 1) * sizeof(wchar_t); LPVOID lpDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (lpDllAddr == NULL) { wprintf(L"[-] Error: Could not allocate memory inside PID (%d).\n", dwProcessId); exit(1); } stub = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (stub == NULL) { wprintf(L"[-] Error: Could not allocate memory for stub.\n"); exit(1); } BOOL bStatus = WriteProcessMemory(hProcess, lpDllAddr, pszLibFile, dwSize, NULL); if (bStatus == 0) { wprintf(L"[-] Error: Could not write any bytes into the PID (%d) address space.\n", dwProcessId); return(1); } threadID = getThreadID(dwProcessId); hThread = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID); if (hThread != NULL) { SuspendThread(hThread); } else printf("could not open thread\n"); ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(hThread, &ctx); oldIP = ctx.Eip; ctx.Eip = (DWORD)stub; ctx.ContextFlags = CONTEXT_CONTROL; VirtualProtect(sc, stubLen, PAGE_EXECUTE_READWRITE, &oldprot); memcpy((void *)((unsigned long)sc + 1), &oldIP, 4); memcpy((void *)((unsigned long)sc + 8), &lpDllAddr, 4); memcpy((void *)((unsigned long)sc + 13), &LoadLibraryAddress, 4); WriteProcessMemory(hProcess, stub, sc, stubLen, NULL); SetThreadContext(hThread, &ctx); ResumeThread(hThread); Sleep(8000); VirtualFreeEx(hProcess, lpDllAddr, dwSize, MEM_DECOMMIT); VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT); CloseHandle(hProcess); CloseHandle(hThread); return(0); }
DWORD demoSuspendInjectResume64(PCWSTR pszLibFile, DWORD dwProcessId) { void *stub; unsigned long threadID, oldprot; HANDLE hThread; CONTEXT ctx; DWORD64 stubLen = sizeof(sc); wprintf(TEXT("[+] Shellcode Length is: %d\n"), stubLen); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (hProcess == NULL) { wprintf(L"[-] Error: Could not open process for PID (%d).\n", dwProcessId); return(1); } DWORD64 LoadLibraryAddress = (DWORD64)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); if (LoadLibraryAddress == NULL) { wprintf(L"[-] Error: Could not find LoadLibraryA function inside kernel32.dll library.\n"); exit(1); } SIZE_T dwSize = (wcslen(pszLibFile) + 1) * sizeof(wchar_t); LPVOID lpDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpDllAddr == NULL) { wprintf(L"[-] Error: Could not allocate memory inside PID (%d).\n", dwProcessId); exit(1); } stub = VirtualAllocEx(hProcess, NULL, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (stub == NULL) { wprintf(L"[-] Error: Could not allocate memory for stub.\n"); exit(1); } SIZE_T nBytesWritten = 0; BOOL bStatus = WriteProcessMemory(hProcess, lpDllAddr, pszLibFile, dwSize, &nBytesWritten); if (bStatus == 0) { wprintf(L"[-] Error: Could not write any bytes into the PID (%d) address space.\n", dwProcessId); return(1); } if (nBytesWritten != dwSize) wprintf(TEXT("[-] Something is wrong!\n")); threadID = getThreadID(dwProcessId); hThread = OpenThread((THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME), false, threadID); if (hThread != NULL) { SuspendThread(hThread); } else wprintf(L"[-] Could not open thread\n"); ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(hThread, &ctx); DWORD64 oldIP = ctx.Rip; ctx.Rip = (DWORD64)stub; ctx.ContextFlags = CONTEXT_CONTROL; memcpy(sc + 3, &oldIP, sizeof(oldIP)); memcpy(sc + 41, &lpDllAddr, sizeof(lpDllAddr)); memcpy(sc + 51, &LoadLibraryAddress, sizeof(LoadLibraryAddress)); #ifdef _DEBUG wprintf(TEXT("[+] Shellcode Launcher Code:\n\t")); for (int i = 0; i < stubLen; i++) wprintf(TEXT("%02x "), sc[i]); wprintf(TEXT("\n")); #endif WriteProcessMemory(hProcess, (void *)stub, &sc, stubLen, NULL); SetThreadContext(hThread, &ctx); ResumeThread(hThread); Sleep(8000); VirtualFreeEx(hProcess, lpDllAddr, dwSize, MEM_DECOMMIT); VirtualFreeEx(hProcess, stub, stubLen, MEM_DECOMMIT); CloseHandle(hProcess); CloseHandle(hThread); return(0); }
__declspec (dllexport) DWORD QueueUserAPCEx(PAPCFUNC pfnApc, HANDLE hThread, DWORD dwData) /* * ------------------------------------------------------ * DOCPUBLIC * Adds a user-mode asynchronous procedure call (APC) object * to the APC queue of the specified thread AND sets this * thread in alertarte state. * * PARAMETERS * Uses the same parameters as QueueUserAPC. * * DESCRIPTION * Adds a user-mode asynchronous procedure call (APC) object * to the APC queue of the specified thread AND sets this * thread in alertarte state. * * RESULTS * 1 Success * 0 Failure * ------------------------------------------------------ */ { DWORD cbReturned; /* trivial case */ if (hThread == GetCurrentThread()) { if (!QueueUserAPC(pfnApc, hThread, dwData)) { return 0; } SleepEx(0, TRUE); return 1; } if (INVALID_HANDLE_VALUE == hDevice /* && !QueueUserAPCEx_Init() */ ) { return 0; } /* probably not necessary */ if (SuspendThread(hThread) == -1) { return 0; } /* Send the APC */ if (!QueueUserAPC(pfnApc, hThread, dwData)) { return 0; } /* Ensure the execution of the APC */ if (DeviceIoControl (hDevice, (DWORD)IOCTL_ALERTDRV_SET_ALERTABLE2, &hThread, sizeof(HANDLE), NULL, 0, &cbReturned, 0)) { } else { return 0; } /* Here, we could even cancel suspended threads */ ResumeThread(hThread); return 1; }
void Thread::suspend() { assert(handle); // Thread object is null int ret = SuspendThread(handle); assert(ret >= 0); // Failed to suspend thread }
tb_bool_t tb_thread_suspend(tb_thread_ref_t thread) { if (thread) return ((DWORD)-1 != SuspendThread((HANDLE)thread))? tb_true : tb_false; return tb_false; }
void cThread::Suspend() { SuspendThread(hThread); }
static int dll_inject(PROCESS_INFORMATION *pinfo, char const *lib) { #ifdef _M_AMD64 # define InstructionPointer Rip # define StackPointer Rsp # define LoaderRegister Rcx # define LoadLibraryAOffset 0x15 /* This payload allows us to load arbitrary module located * at the end of this buffer */ static uint8_t const loader[] = { "\x55" /* push rbp */ "\x48\x89\xE5" /* mov rbp,rsp */ "\x48\x83\xEC\x20" /* sub rsp,byte +0x20 */ "\x48\x83\xE4\xF0" /* and rsp,byte -0x10 */ "\x48\x8D\x0D\x14\x00\x00\x00" /* lea rcx,[rel 0x27] */ "\x48\xB8________" /* mov rax, LoadLibraryA */ "\xFF\xD0" /* call rax */ "\x48\x85\xC0" /* test rax,rax */ "\x75\x01" /* jnz 0x25 */ "\xCC" /* int3 */ "\xC9" /* leave */ "\xC3" /* ret */ }; #elif defined (_M_IX86) # define InstructionPointer Eip # define StackPointer Esp # define LoaderRegister Eax /* It seems the Windows loader store the oep as the first param * but by a side effect it's also contained in eax register */ # define loader loader32 # define LoadLibraryAOffset 0x04 /* This payload allows us to load arbitrary module located * at the end of this buffer */ static uint8_t const loader[] = { "\x60" /* pushad */ "\xEB\x0E" /* jmp short 0x11 */ "\xB8____" /* mov eax,LoadLibraryA */ "\xFF\xD0" /* call eax */ "\x85\xC0" /* test eax,eax */ "\x75\x01" /* jnz 0xf */ "\xCC" /* int3 */ "\x61" /* popad */ "\xC3" /* ret */ "\xE8\xED\xFF\xFF\xFF" /* call dword 0x3 */ }; #else # error Unimplemented architecture ! #endif /* We use this code to make the targeted process wait for us */ static uint8_t const wait[] = "\xeb\xfe"; /* jmp $-1 */ size_t wait_len = sizeof(wait) - 1; void *process = pinfo->hProcess; void *thread = pinfo->hThread; SIZE_T written = 0; BOOL tmp; /* Payload */ size_t payload_len = sizeof(loader) - 1 + strlen(lib) + 1; uint8_t *payload = malloc(payload_len); if (payload == NULL) goto error; /* Use the main thread to inject our library */ CONTEXT ctxt; ctxt.ContextFlags = CONTEXT_FULL; if (!GetThreadContext(thread, &ctxt)) goto error; /* Make the target program wait when it reaches the original entry * point, because we can't do many thing from the Windows loader */ DWORD_PTR oep = ctxt.LoaderRegister; /* Original Entry Point */ uint8_t orig_data[2]; tmp = ReadProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written); if (!tmp || written != sizeof(orig_data)) goto error; /* save original opcode */ tmp = WriteProcessMemory(process, (LPVOID)oep, wait, wait_len, &written); if (!tmp || written != wait_len) goto error; /* write jmp short $-1 */ if (!FlushInstructionCache(process, (LPVOID)oep, wait_len)) goto error; if (ResumeThread(thread) == (DWORD)-1) goto error; /* Stop when the program reachse the oep */ while (oep != ctxt.InstructionPointer) { if (!GetThreadContext(thread, &ctxt)) goto error; Sleep(10); } if (SuspendThread(thread) == (DWORD)-1) goto error; /* Resolve LoadLibraryA from the target process memory context */ DWORD pid = pinfo->dwProcessId; void *rldlib = get_proc_address(process, pid, "LoadLibraryA"); if (rldlib == NULL) goto error; void *rpl = VirtualAllocEx(process, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (rpl == NULL) goto error; /* Emulate a call to the loader code, thus the ret instruction from * loader will get (e|r)ip back to the original entry point */ ctxt.StackPointer -= sizeof(oep); tmp = WriteProcessMemory(process, (LPVOID)ctxt.StackPointer, &oep, sizeof(oep), &written); if (!tmp || written != sizeof(oep)) goto error; ctxt.InstructionPointer = (DWORD_PTR)rpl; if (!SetThreadContext(thread, &ctxt)) goto error; /* Forge the payload */ memcpy(payload, loader, sizeof(loader) - 1); /* Write the address of LoadLibraryA */ memcpy(payload + LoadLibraryAOffset, &rldlib, sizeof(rldlib)); /* Write the first parameter of LoadLibraryA */ strcpy((char *)(payload + sizeof(loader) - 1), lib); tmp = WriteProcessMemory(process, rpl, payload, payload_len, &written); if (!tmp || written != payload_len) goto error; /* Restore original opcode */ tmp = WriteProcessMemory(process, (LPVOID)oep, orig_data, sizeof(orig_data), &written); if (!tmp || written != sizeof(orig_data)) goto error; if (!FlushInstructionCache(process, rpl, payload_len)) goto error; if (!FlushInstructionCache(process, (LPVOID)oep, sizeof(orig_data))) goto error; /* We must not free remote allocated memory since they will be used * after the process will be resumed */ free(payload); return 0; error: free(payload); return -1; }
void opzThread::Suspend() { SuspendThread(_hThread); }
/* * Main Test Case worker thread which will suspend and resume all other worker threads */ DWORD PALAPI suspendandresumethreads( LPVOID lpParam ) { unsigned int loopcount = REPEAT_COUNT; int Id=(int)lpParam; unsigned int i,j,k; DWORD dwStart; DWORD dwWaitResult=0; DWORD dwLastError = 0; struct statistics stats; struct statistics* buffer; //Initialize the Statistics Structure stats.relationId = RELATION_ID; stats.processId = USE_PROCESS_COUNT; stats.operationsFailed = 0; stats.operationsPassed = 0; stats.operationsTotal = 0; stats.operationTime = 0; //Wait for event to signal to start test WaitForSingleObject(g_hEvent,INFINITE); if (WAIT_OBJECT_0 != dwWaitResult) { Fail ("suspendandresumethreads: Wait for Single Object (g_hEvent) failed. Failing test.\n" "GetLastError returned %d\n", GetLastError()); } //Capture Start Import dwStart = GetTickCount(); for(i = 0; i < loopcount; i++) { failFlag = false; //Suspend Worker Threads for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++) { for (j=0;j<4;j++) { if (-1 == SuspendThread(hThread[j][k])) { //If the operation indicate failure failFlag = true; } } } //Resume Worker Threads for (k=0;k<WORKER_THREAD_MULTIPLIER_COUNT;k++) { for (j=0;j<4;j++) { //Only suspend if not already in suspended state if (-1 == ResumeThread(hThread[j][k])) { //If the operation indicate failure failFlag = true; } } } //Check for Fail Flag. If set increment number of failures // If Fail flag not set then increment number of operations and number of passe if (failFlag == true) { stats.operationsFailed++; } else { stats.operationsPassed +=1; } stats.operationsTotal +=1; } stats.operationTime = GetTickCount() - dwStart; /*Trace("\n\n\n\nOperation Time: %d milliseconds\n", stats.operationTime); Trace("Operation Passed: %d\n", stats.operationsPassed); Trace("Operation Total: %d\n", stats.operationsTotal); Trace("Operation Failed: %d\n", stats.operationsFailed); */ if(resultBuffer->LogResult(Id, (char *)&stats)) { Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT); } buffer = (struct statistics *)resultBuffer->getResultBuffer(Id); //Trace("\n%d,%d,%d,%lu\n", buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime ); return 0; }
int pthread_cancel (pthread_t thread) /* * ------------------------------------------------------ * DOCPUBLIC * This function requests cancellation of 'thread'. * * PARAMETERS * thread * reference to an instance of pthread_t * * * DESCRIPTION * This function requests cancellation of 'thread'. * NOTE: cancellation is asynchronous; use pthread_join to * wait for termination of 'thread' if necessary. * * RESULTS * 0 successfully requested cancellation, * ESRCH no thread found corresponding to 'thread', * ENOMEM implicit self thread create failed. * ------------------------------------------------------ */ { int result; int cancel_self; pthread_t self; if (thread == NULL ) { return ESRCH; } result = 0; if ((self = pthread_self()) == NULL) { return ENOMEM; }; /* * FIXME!! * * Can a thread cancel itself? * * The standard doesn't * specify an error to be returned if the target * thread is itself. * * If it may, then we need to ensure that a thread can't * deadlock itself trying to cancel itself asyncronously * (pthread_cancel is required to be an async-cancel * safe function). */ cancel_self = pthread_equal(thread, self); /* * Lock for async-cancel safety. */ (void) pthread_mutex_lock(&thread->cancelLock); if (thread->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS && thread->cancelState == PTHREAD_CANCEL_ENABLE && thread->state < PThreadStateCanceling ) { if (cancel_self) { thread->state = PThreadStateCanceling; thread->cancelState = PTHREAD_CANCEL_DISABLE; (void) pthread_mutex_unlock(&thread->cancelLock); ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } else { HANDLE threadH = thread->threadH; SuspendThread(threadH); if (WaitForSingleObject(threadH, 0) == WAIT_TIMEOUT ) { CONTEXT context; thread->state = PThreadStateCanceling; thread->cancelState = PTHREAD_CANCEL_DISABLE; context.ContextFlags = CONTEXT_CONTROL; GetThreadContext(threadH, &context); PTW32_PROGCTR(context) = (DWORD) ptw32_cancel_self; SetThreadContext(threadH, &context); (void) pthread_mutex_unlock(&thread->cancelLock); ResumeThread(threadH); } } } else { /* * Set for deferred cancellation. */ if ( thread->state >= PThreadStateCanceling || !SetEvent (thread->cancelEvent)) { result = ESRCH; } (void) pthread_mutex_unlock(&thread->cancelLock); } return (result); }
//int _tmain( int argc, TCHAR* argv[] ) int main( void ) { STARTUPINFO si; PROCESS_INFORMATION pi; TCHAR* cmd; BOOL option; BOOL opt_m; BOOL installed; HMODULE ansi; int rc = 0; int argc; LPWSTR* argv = CommandLineToArgvW( GetCommandLine(), &argc ); if (argc > 1) { if (lstrcmp( argv[1], L"--help" ) == 0 || (argv[1][0] == '-' && (argv[1][1] == '?' || argv[1][1] == 'h')) || (argv[1][0] == '/' && argv[1][1] == '?')) { help(); return rc; } if (lstrcmp( argv[1], L"--version" ) == 0) { _putws( L"ANSICON (" BITS L"-bit) version " PVERS L" (" PDATE L")." ); return rc; } } #if (MYDEBUG > 1) DEBUGSTR( NULL ); // create a new file #endif option = (argc > 1 && argv[1][0] == '-'); if (option && (towlower( argv[1][1] ) == 'i' || towlower( argv[1][1] ) == 'u')) { process_autorun( argv[1][1] ); argv[1][1] = 'p'; } get_original_attr(); opt_m = FALSE; if (option && argv[1][1] == 'm') { WORD attr = 7; if (iswxdigit( argv[1][2] )) { attr = iswdigit( argv[1][2] ) ? argv[1][2] - '0' : (argv[1][2] | 0x20) - 'a' + 10; if (iswxdigit( argv[1][3])) { attr <<= 4; attr |= iswdigit( argv[1][3] ) ? argv[1][3] - '0' : (argv[1][3] | 0x20) - 'a' + 10; } } SetConsoleTextAttribute( hConOut, attr ); opt_m = TRUE; ++argv; --argc; option = (argc > 1 && argv[1][0] == '-'); } installed = (GetEnvironmentVariable( L"ANSICON", NULL, 0 ) != 0); if (option && argv[1][1] == 'p') { // If it's already installed, there's no need to do anything. if (installed) ; else if (GetParentProcessInfo( &pi )) { pi.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId ); pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId ); SuspendThread( pi.hThread ); if (!Inject( &pi )) { _putws( L"ANSICON: parent process type is not supported." ); rc = 1; } ResumeThread( pi.hThread ); CloseHandle( pi.hThread ); CloseHandle( pi.hProcess ); } else { _putws( L"ANSICON: could not obtain the parent process." ); rc = 1; } } else { ansi = 0; if (!installed) { ansi = LoadLibrary( L"ANSI" BITS L".dll" ); if (!ansi) { fputws( L"ANSICON: failed to load ANSI" BITS L".dll.\n", stderr ); rc = 1; } } if (option && (argv[1][1] == 't' || argv[1][1] == 'T')) { BOOL title = (argv[1][1] == 'T'); if (argc == 2) { argv[2] = L"-"; ++argc; } for (; argc > 2; ++argv, --argc) { if (title) wprintf( L"==> %s <==\n", argv[2] ); display( argv[2], title ); if (title) putwchar( '\n' ); } } else { // Retrieve the original command line, skipping our name and the option. cmd = skip_spaces( skip_arg( skip_spaces( GetCommandLine() ) ) ); if (opt_m) cmd = skip_spaces( skip_arg( cmd ) ); if (cmd[0] == '-' && (cmd[1] == 'e' || cmd[1] == 'E')) { fputws( cmd + 3, stdout ); if (cmd[1] == 'e') putwchar( '\n' ); } else if (!_isatty( 0 ) && *cmd == '\0') { display( L"-", FALSE ); } else { if (*cmd == '\0') { cmd = _wgetenv( L"ComSpec" ); if (cmd == NULL) cmd = L"cmd"; } ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); if (CreateProcess( NULL, cmd, NULL,NULL, TRUE, 0, NULL,NULL, &si, &pi )) { BOOL console = FALSE; TCHAR name[MAX_PATH]; DWORD rc; CoInitialize( NULL ); do { // When I first tried doing this, it took a little while to // succeed. Testing again shows it works immediately - perhaps the // CoInitialize introduces enough of a delay. Still, play it safe // and keep trying. And if you're wondering why I do it at all, // ProcessType may detect GUI, even for a console process. That's // fine after injection (including -p), but not here. We *need* to // suspend our own execution whilst running the child, otherwise // bad things happen (besides which, I want to restore the original // attributes when the child exits). if (GetModuleFileNameEx( pi.hProcess, NULL, name, lenof(name) )) { DWORD_PTR info; info = SHGetFileInfo( name, 0, NULL, 0, SHGFI_EXETYPE ); if (info == 0x00004550) // console PE console = TRUE; DEBUGSTR( L"%s", name ); DEBUGSTR( L" %s (%p)", (console) ? L"Console" : L"Not console", info ); break; } Sleep( 10 ); } while (GetExitCodeProcess( pi.hProcess, &rc ) && rc == STILL_ACTIVE); CoUninitialize(); if (console) { SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE ); WaitForSingleObject( pi.hProcess, INFINITE ); } CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } else { *skip_arg( cmd ) = '\0'; wprintf( L"ANSICON: '%s' could not be executed.\n", cmd ); rc = 1; } } } if (ansi) FreeLibrary( ansi ); } set_original_attr(); return rc; }
static void dump_thread(void *arg) { HANDLE dbghelp; BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL); BOOL (WINAPI *pSymCleanup)(HANDLE); BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64); DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64); BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *); BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *); HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD); DWORD tid = *(DWORD *)arg; HANDLE ph; HANDLE th; dbghelp = LoadLibrary("dbghelp.dll"); if (!dbghelp) return; pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize"); pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup"); pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64"); pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64"); pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr"); pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64"); pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread"); if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 && pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) { SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); ph = GetCurrentProcess(); pSymInitialize(ph, NULL, TRUE); th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid); if (th) { if (SuspendThread(th) != (DWORD)-1) { CONTEXT context; memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_FULL; if (GetThreadContext(th, &context)) { char libpath[MAX_PATH]; char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; SYMBOL_INFO *info = (SYMBOL_INFO *)buf; DWORD mac; STACKFRAME64 frame; memset(&frame, 0, sizeof(frame)); #if defined(_M_AMD64) || defined(__x86_64__) mac = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Rip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Rbp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Rsp; #elif defined(_M_IA64) || defined(__ia64__) mac = IMAGE_FILE_MACHINE_IA64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.StIIP; frame.AddrBStore.Mode = AddrModeFlat; frame.AddrBStore.Offset = context.RsBSP; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.IntSp; #else /* i386 */ mac = IMAGE_FILE_MACHINE_I386; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Eip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Ebp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Esp; #endif while (pStackWalk64(mac, ph, th, &frame, &context, NULL, NULL, NULL, NULL)) { DWORD64 addr = frame.AddrPC.Offset; IMAGEHLP_LINE64 line; DWORD64 displacement; DWORD tmp; if (addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0) break; memset(buf, 0, sizeof(buf)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (pSymFromAddr(ph, addr, &displacement, info)) { if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) fprintf(stderr, "%s", libpath); fprintf(stderr, "(%s+0x%I64x)", info->Name, displacement); } fprintf(stderr, " [0x%p]", (void *)(VALUE)addr); memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); if (pSymGetLineFromAddr64(ph, addr, &tmp, &line)) fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber); fprintf(stderr, "\n"); } } ResumeThread(th); } CloseHandle(th); } pSymCleanup(ph); } FreeLibrary(dbghelp); }
int pthread_cancel (pthread_t thread) /* * ------------------------------------------------------ * DOCPUBLIC * This function requests cancellation of 'thread'. * * PARAMETERS * thread * reference to an instance of pthread_t * * * DESCRIPTION * This function requests cancellation of 'thread'. * NOTE: cancellation is asynchronous; use pthread_join to * wait for termination of 'thread' if necessary. * * RESULTS * 0 successfully requested cancellation, * ESRCH no thread found corresponding to 'thread', * ENOMEM implicit self thread create failed. * ------------------------------------------------------ */ { int result; int cancel_self; pthread_t self; ptw32_thread_t * tp; result = pthread_kill (thread, 0); if (0 != result) { return result; } if ((self = pthread_self ()).p == NULL) { return ENOMEM; }; /* * FIXME!! * * Can a thread cancel itself? * * The standard doesn't * specify an error to be returned if the target * thread is itself. * * If it may, then we need to ensure that a thread can't * deadlock itself trying to cancel itself asyncronously * (pthread_cancel is required to be an async-cancel * safe function). */ cancel_self = pthread_equal (thread, self); tp = (ptw32_thread_t *) thread.p; /* * Lock for async-cancel safety. */ (void) pthread_mutex_lock (&tp->cancelLock); if (tp->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS && tp->cancelState == PTHREAD_CANCEL_ENABLE && tp->state < PThreadStateCanceling) { if (cancel_self) { tp->state = PThreadStateCanceling; tp->cancelState = PTHREAD_CANCEL_DISABLE; (void) pthread_mutex_unlock (&tp->cancelLock); ptw32_throw (PTW32_EPS_CANCEL); /* Never reached */ } else { HANDLE threadH = tp->threadH; SuspendThread (threadH); if (WaitForSingleObject (threadH, 0) == WAIT_TIMEOUT) { tp->state = PThreadStateCanceling; tp->cancelState = PTHREAD_CANCEL_DISABLE; /* * If alertdrv and QueueUserAPCEx is available then the following * will result in a call to QueueUserAPCEx with the args given, otherwise * this will result in a call to ptw32_RegisterCancelation and only * the threadH arg will be used. */ ptw32_register_cancelation (ptw32_cancel_callback, threadH, 0); (void) pthread_mutex_unlock (&tp->cancelLock); //ResumeThread (threadH); } } } else { /* * Set for deferred cancellation. */ if (tp->state < PThreadStateCancelPending) { tp->state = PThreadStateCancelPending; if (!SetEvent (tp->cancelEvent)) { result = ESRCH; } } else if (tp->state >= PThreadStateCanceling) { result = ESRCH; } (void) pthread_mutex_unlock (&tp->cancelLock); } return (result); }
/* this thread assists with the returns from simulated interrupts ideally, the interrupthandler would just assume the state right before the interrupt, but this is not possible given the x86 and nt, so the interrupt handling thread has to suspend itself, and let some other thread manipulate its state while it is suspended. when this thread runs, interrupts will be disabled, so we reenable them once it is finished. */ DWORD WINAPI interrupt_return_assist(LPVOID ptr) { signal_queue_t *sq; int scount, rcount; int success = FALSE; CONTEXT context; if (DEBUG) kprintf("IRA:starting ...\n"); for(;;) { /* wait politely until we are needed */ WaitOnObject(cleanup); if (DEBUG) kprintf("IRA:woken up ...\n"); WaitOnObject(mutex); { success = FALSE; sq = signalq; signalq = signalq->next; assert(signalq == NULL); /* wait for the system thread to enter a "safe" state */ while(readytoreturn != TRUE) SwitchToThread(); while(success != TRUE) { scount = SuspendThread(sq->threadid); memset(&context, 0, sizeof(CONTEXT)); #ifdef WINCE context.ContextFlags = CONTEXT_FULL; #else context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; #endif AbortOnError(GetThreadContext(system_thread, &context)); if (DEBUG) kprintf("IRA:system thread is at 0x%x.\n", EIP); if((EIP >= (unsigned int)loopforever_start_address && EIP <= (unsigned int)loopforever_end_address)) { if (DEBUG) kprintf("IRA:enabling interrupts.\n"); interrupt_level = ENABLED; AbortOnError(SetThreadContext(sq->threadid, sq->context)); rcount = ResumeThread(sq->threadid); if (DEBUG) kprintf("IRA:Interrupt return assist scount %d rcount %d\n", scount, rcount); assert(rcount >= scount + 1); success = TRUE; } else { ResumeThread(system_thread); ReleaseMutex(mutex); SwitchToThread(); WaitOnObject(mutex); } } } ReleaseMutex(mutex); free(sq); } /* never reached */ return 0; }
void pause() const { _mutex.lock(); SuspendThread(_handle); _mutex.unlock(); }
/* * Send an interrupt to the system thread: adjust its stack to call * the appropriate interrupt handler with the specified argument. the * "type" argument identifies interrupt-specific processing which must * be done, in particular, what we should do if interrupts are * disabled or the system thread is in a non-preemptable state * (e.g. executing a system library function). clock interrupts are * dropped, network interrupts are deferred. this function replaces * code which used to be common to clock_poll and network_poll. */ void send_interrupt(int type, void* arg) { CONTEXT context; int safe_to_proceed = 0; int drop_interrupt = 0; interrupt_queue_t* interrupt_info = NULL; for (;;) { WaitOnObject(mutex); /* need to protect this code: we only activate the interrupt if interrupts are actually enabled, but we also need to ensure they are not disabled after we test -- so we suspend the system thread first. */ SuspendThread(system_thread); memset(&context, 0, sizeof(CONTEXT)); #ifdef WINCE context.ContextFlags = CONTEXT_FULL; #else context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; #endif /* Warning: a printf here makes the system lock */ AbortOnError(GetThreadContext(system_thread, &context)); /* find interrupt description in the interrupt queue */ interrupt_info = interrupt_queue; while (interrupt_info!=NULL && interrupt_info->type!=type) interrupt_info = interrupt_info->next; if (interrupt_info == NULL) { /* * we couldn't find the interrupt with type "type" so we crash the * sistem. */ kprintf("INT ERR: An interrupt of the unregistered type %d was received.\n", type); AbortOnCondition(1,"Crashing."); } else { /* * interrupt-type-specific processing: can we interrupt now? If we * ended up interrupting the process at a time when it is in some non-minithread-safe * Windows library, then defer or drop the interrupt. */ switch (interrupt_info->property){ case INTERRUPT_DROP: if (interrupt_level == DISABLED || (EIP < start_address) || (EIP > end_address)) { drop_interrupt = 1; } else { //interrupt_level = DISABLED; safe_to_proceed = 1; } break; case INTERRUPT_DEFER: if (interrupt_level == ENABLED && (EIP >= start_address) && (EIP <= end_address)) { interrupt_level = DISABLED; safe_to_proceed = 1; } break; default: break; } } if (safe_to_proceed == 1) break; else { ResumeThread(system_thread); ReleaseMutex(mutex); if (DEBUG) { switch (interrupt_info->property) { case INTERRUPT_DROP: kprintf("Interrupt of type %d dropped, eip = 0x%x.\n", interrupt_info->type, EIP); break; case INTERRUPT_DEFER: kprintf("Interrupt of type %d deffered, eip = 0x%x.\n", interrupt_info->type, EIP); break; } } } if (drop_interrupt == 1) return; else SwitchToThread(); } /* now fix the system thread's stack so it runs run_user_handler */ { int stack; int oldpc = 0; //if (DEBUG) { //kprintf("Interrupts are enabled, system thread pc = 0x%x\n", EIP); //kprintf("Adjusting system thread context ...\n"); // } /* set the interrupt number */ /* arg->intnumber = ++intnumber; */ oldpc = EIP; stack = ESP; /* Esp == extended stack pointer */ /* safe to do a printf because other thread is stunned in user code */ // if (DEBUG) //kprintf("Suspended system thread, adjusting stack, sp = 0x%x\n", stack); stack -= (sizeof(CONTEXT) + 64); /* 64 is slop */ memcpy((int *) stack, &context, sizeof(CONTEXT)); EIP = (int) ((void *) receive_interrupt); REG1 = stack; /*pointer to context*/ REG2 = (int) type; /*type, second argument */ #ifndef WINCE /* for x86 put arg pointer on the stack since only two parameters can be passed in registers. */ stack-=sizeof(void*); *((int*)stack)=(int) arg; stack-=sizeof(void*); #else /* for ARM put the third argument in R2 */ context.R2 = (int) arg; #endif ESP = stack; AbortOnError(SetThreadContext(system_thread, &context)); AbortOnError(GetThreadContext(system_thread, &context)); ResumeThread(system_thread); } ReleaseMutex(mutex); }
void Thread::suspend() { SuspendThread(m_handle); }
bool windows_suspend(DWORD pid) { // make sure we haven't already suspended this process, then allocate // a SuspendedProcess object and add it to the hash table // SuspendedProcess* sp; int ret = suspended_processes.lookup(pid, sp); ASSERT(ret == -1); sp = new SuspendedProcess(11, hash_func); ASSERT(sp != NULL); ret = suspended_processes.insert(pid, sp); ASSERT(ret != -1); // we need to loop until iterating through the thread list for this // process shows that all threads are suspended // bool finished = false; while (!finished) { // assume we're going to succeed on this iteration until // proven otherwise // finished = true; // get the list of threads for this process // ExtArray<DWORD> tid_array; int num_tids = sys_info.GetTIDs(pid, tid_array); if (num_tids == 0) { // TODO: we need to handle this case!!! // EXCEPT("windows_suspend_process failed: can't get threads for pid %u", pid); } // go through the thread list, calling SuspendThread on each // for (int i = 0; i < num_tids; i++) { // see if we already have a record for this thread // SuspendedThread* st; ret = sp->lookup(tid_array[i], st); if (ret == -1) { // no record yet; open up this thread's handle // HANDLE handle = OpenThread(THREAD_SUSPEND_RESUME, FALSE, tid_array[i]); if (handle == NULL) { // the thread probably exited; however, it may have called ResumeThread // or CreateThread first, so we'll have to loop again // finished = false; dprintf(D_FULLDEBUG, "windows_suspend_process: OpenThread error: %u\n", GetLastError()); continue; } // now that we have a handle, create a record for this thread // st = new SuspendedThread; ASSERT(st != NULL); st->handle = handle; st->num_suspends = 0; ret = sp->insert(tid_array[i], st); ASSERT(ret != -1); } // now suspend the thread // DWORD result = SuspendThread(st->handle); if (result == (DWORD)-1) { // how can this happen? maybe the thread exited? // finished = false; dprintf(D_FULLDEBUG, "windows_suspend_process: SuspendThread error: %u\n", GetLastError()); continue; } // if the thread was not suspended prior to our SuspendThread call, // it may have called CreateThread or ResumeThread so we need to loop // at least one more time // if (result == 0) { finished = false; } // keep track of how many suspends we've sent this thread // st->num_suspends++; } } return true; }