⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32_threads.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 4 页
字号:
    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (t = GC_threads[i]; t != 0; t = t -> next) {        if (t -> stack_base != 0 && t -> suspended	    && t -> id != thread_id) {          if (ResumeThread(t -> handle) == (DWORD)-1)	    ABORT("ResumeThread failed");          t -> suspended = FALSE;        }      }    }  }  GC_please_stop = FALSE;}# ifdef MSWINCE    /* The VirtualQuery calls below won't work properly on WinCE, but	*/    /* since each stack is restricted to an aligned 64K region of	*/    /* virtual memory we can just take the next lowest multiple of 64K.	*/#   define GC_get_stack_min(s) \        ((ptr_t)(((DWORD)(s) - 1) & 0xFFFF0000))# else    static ptr_t GC_get_stack_min(ptr_t s)    {	ptr_t bottom;	MEMORY_BASIC_INFORMATION info;	VirtualQuery(s, &info, sizeof(info));	do {	    bottom = info.BaseAddress;	    VirtualQuery(bottom - 1, &info, sizeof(info));	} while ((info.Protect & PAGE_READWRITE)		 && !(info.Protect & PAGE_GUARD));	return(bottom);    }# endifvoid GC_push_stack_for(GC_thread thread){    int dummy;    ptr_t sp, stack_min;    DWORD me = GetCurrentThreadId();    if (thread -> stack_base) {      if (thread -> id == me) {	sp = (ptr_t) &dummy;      } else {        CONTEXT context;        context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;        if (!GetThreadContext(thread -> handle, &context))	  ABORT("GetThreadContext failed");        /* Push all registers that might point into the heap.  Frame	*/        /* pointer registers are included in case client code was	*/        /* compiled with the 'omit frame pointer' optimisation.		*/#       define PUSH1(reg) GC_push_one((word)context.reg)#       define PUSH2(r1,r2) PUSH1(r1), PUSH1(r2)#       define PUSH4(r1,r2,r3,r4) PUSH2(r1,r2), PUSH2(r3,r4)#       if defined(I386)          PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);	  sp = (ptr_t)context.Esp;#	elif defined(X86_64)	  PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi);	  PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15);	  sp = (ptr_t)context.Rsp;#       elif defined(ARM32)	  PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11),PUSH1(R12);	  sp = (ptr_t)context.Sp;#       elif defined(SHx)	  PUSH4(R0,R1,R2,R3), PUSH4(R4,R5,R6,R7), PUSH4(R8,R9,R10,R11);	  PUSH2(R12,R13), PUSH1(R14);	  sp = (ptr_t)context.R15;#       elif defined(MIPS)	  PUSH4(IntAt,IntV0,IntV1,IntA0), PUSH4(IntA1,IntA2,IntA3,IntT0);	  PUSH4(IntT1,IntT2,IntT3,IntT4), PUSH4(IntT5,IntT6,IntT7,IntS0);	  PUSH4(IntS1,IntS2,IntS3,IntS4), PUSH4(IntS5,IntS6,IntS7,IntT8);	  PUSH4(IntT9,IntK0,IntK1,IntS8);	  sp = (ptr_t)context.IntSp;#       elif defined(PPC)	  PUSH4(Gpr0, Gpr3, Gpr4, Gpr5),  PUSH4(Gpr6, Gpr7, Gpr8, Gpr9);	  PUSH4(Gpr10,Gpr11,Gpr12,Gpr14), PUSH4(Gpr15,Gpr16,Gpr17,Gpr18);	  PUSH4(Gpr19,Gpr20,Gpr21,Gpr22), PUSH4(Gpr23,Gpr24,Gpr25,Gpr26);	  PUSH4(Gpr27,Gpr28,Gpr29,Gpr30), PUSH1(Gpr31);	  sp = (ptr_t)context.Gpr1;#       elif defined(ALPHA)	  PUSH4(IntV0,IntT0,IntT1,IntT2), PUSH4(IntT3,IntT4,IntT5,IntT6);	  PUSH4(IntT7,IntS0,IntS1,IntS2), PUSH4(IntS3,IntS4,IntS5,IntFp);	  PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9);	  PUSH4(IntT10,IntT11,IntT12,IntAt);	  sp = (ptr_t)context.IntSp;#       else#         error "architecture is not supported"#       endif      } /* ! current thread */      stack_min = GC_get_stack_min(thread->stack_base);      if (sp >= stack_min && sp < thread->stack_base) {#       if DEBUG_WIN32_PTHREADS || DEBUG_WIN32_THREADS \           || DEBUG_CYGWIN_THREADS	  GC_printf("Pushing thread from %p to %p for 0x%x from 0x%x\n",		    sp, thread -> stack_base, thread -> id, me);#       endif        GC_push_all_stack(sp, thread->stack_base);      } else {        WARN("Thread stack pointer 0x%lx out of range, pushing everything\n",	     (unsigned long)(size_t)sp);        GC_push_all_stack(stack_min, thread->stack_base);      }    } /* thread looks live */}void GC_push_all_stacks(void){  DWORD me = GetCurrentThreadId();  GC_bool found_me = FALSE;  size_t nthreads = 0;    if (GC_win32_dll_threads) {    int i;    LONG my_max = GC_get_max_thread_index();    for (i = 0; i <= my_max; i++) {      GC_thread t = (GC_thread)(dll_thread_table + i);      if (t -> in_use) {        ++nthreads;        GC_push_stack_for(t);        if (t -> id == me) found_me = TRUE;      }    }  } else {    GC_thread t;    int i;    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (t = GC_threads[i]; t != 0; t = t -> next) {        ++nthreads;        if (!KNOWN_FINISHED(t)) GC_push_stack_for(t);        if (t -> id == me) found_me = TRUE;      }    }  }  if (GC_print_stats == VERBOSE) {    GC_log_printf("Pushed %d thread stacks ", nthreads);    if (GC_win32_dll_threads) {    	GC_log_printf("based on DllMain thread tracking\n");    } else {    	GC_log_printf("\n");    }  }  if (!found_me && !GC_in_thread_creation)    ABORT("Collecting from unknown thread.");}void GC_get_next_stack(char *start, char **lo, char **hi){    int i;#   define ADDR_LIMIT (char *)(-1L)    char * current_min = ADDR_LIMIT;    if (GC_win32_dll_threads) {      LONG my_max = GC_get_max_thread_index();        for (i = 0; i <= my_max; i++) {    	ptr_t s = (ptr_t)(dll_thread_table[i].stack_base);	if (0 != s && s > start && s < current_min) {	    current_min = s;	}      }    } else {      for (i = 0; i < THREAD_TABLE_SZ; i++) {	GC_thread t;        for (t = GC_threads[i]; t != 0; t = t -> next) {	  ptr_t s = (ptr_t)(t -> stack_base);	  if (0 != s && s > start && s < current_min) {	    current_min = s;	  }        }      }    }    *hi = current_min;    if (current_min == ADDR_LIMIT) {    	*lo = ADDR_LIMIT;	return;    }    *lo = GC_get_stack_min(current_min);    if (*lo < start) *lo = start;}#ifndef GC_PTHREADS/* We have no DllMain to take care of new threads.  Thus we	*//* must properly intercept thread creation.			*/typedef struct {    LPTHREAD_START_ROUTINE start;    LPVOID param;} thread_args;static DWORD WINAPI thread_start(LPVOID arg);void * GC_win32_start_inner(struct GC_stack_base *sb, LPVOID arg){    void * ret;    thread_args *args = (thread_args *)arg;#   if DEBUG_WIN32_THREADS      GC_printf("thread 0x%x starting...\n", GetCurrentThreadId());#   endif    GC_register_my_thread(sb); /* This waits for an in-progress GC. */    /* Clear the thread entry even if we exit with an exception.	*/    /* This is probably pointless, since an uncaught exception is	*/    /* supposed to result in the process being killed.			*/#ifndef __GNUC__    __try {#endif /* __GNUC__ */	ret = (void *)(size_t)args->start (args->param);#ifndef __GNUC__    } __finally {#endif /* __GNUC__ */	GC_unregister_my_thread();	GC_free(args);#ifndef __GNUC__    }#endif /* __GNUC__ */#   if DEBUG_WIN32_THREADS      GC_printf("thread 0x%x returned from start routine.\n",		GetCurrentThreadId());#   endif    return ret;}DWORD WINAPI GC_win32_start(LPVOID arg){    return (DWORD)(size_t)GC_call_with_stack_base(GC_win32_start_inner, arg);}GC_API HANDLE WINAPI GC_CreateThread(    LPSECURITY_ATTRIBUTES lpThreadAttributes,     DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,     LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ){    HANDLE thread_h = NULL;    thread_args *args;    if (!parallel_initialized) GC_init_parallel();    		/* make sure GC is initialized (i.e. main thread is attached,		   tls initialized) */#   if DEBUG_WIN32_THREADS      GC_printf("About to create a thread from 0x%x\n", GetCurrentThreadId());#   endif    if (GC_win32_dll_threads) {      return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,                        lpParameter, dwCreationFlags, lpThreadId);    } else {      args = GC_malloc_uncollectable(sizeof(thread_args)); 	/* Handed off to and deallocated by child thread.	*/      if (0 == args) {	SetLastError(ERROR_NOT_ENOUGH_MEMORY);        return NULL;      }      /* set up thread arguments */    	args -> start = lpStartAddress;    	args -> param = lpParameter;      GC_need_to_lock = TRUE;      thread_h = CreateThread(lpThreadAttributes,    			      dwStackSize, GC_win32_start,    			      args, dwCreationFlags,    			      lpThreadId);      if( thread_h == 0 ) GC_free( args );      return thread_h;    }}void WINAPI GC_ExitThread(DWORD dwExitCode){  GC_unregister_my_thread();  ExitThread(dwExitCode);}uintptr_t GC_beginthreadex(    void *security, unsigned stack_size,    unsigned ( __stdcall *start_address )( void * ),    void *arglist, unsigned initflag, unsigned *thrdaddr){    uintptr_t thread_h = -1L;    thread_args *args;    if (!parallel_initialized) GC_init_parallel();    		/* make sure GC is initialized (i.e. main thread is attached,		   tls initialized) */#   if DEBUG_WIN32_THREADS      GC_printf("About to create a thread from 0x%x\n", GetCurrentThreadId());#   endif    if (GC_win32_dll_threads) {      return _beginthreadex(security, stack_size, start_address,                            arglist, initflag, thrdaddr);    } else {      args = GC_malloc_uncollectable(sizeof(thread_args)); 	/* Handed off to and deallocated by child thread.	*/      if (0 == args) {	SetLastError(ERROR_NOT_ENOUGH_MEMORY);        return (uintptr_t)(-1);      }      /* set up thread arguments */    	args -> start = (LPTHREAD_START_ROUTINE)start_address;    	args -> param = arglist;      GC_need_to_lock = TRUE;      thread_h = _beginthreadex(security, stack_size,      		 (unsigned (__stdcall *) (void *))GC_win32_start,                                args, initflag, thrdaddr);      if( thread_h == 0 ) GC_free( args );      return thread_h;    }}void GC_endthreadex(unsigned retval){  GC_unregister_my_thread();  _endthreadex(retval);}#endif /* !GC_PTHREADS */#ifdef MSWINCEtypedef struct {    HINSTANCE hInstance;    HINSTANCE hPrevInstance;    LPWSTR lpCmdLine;    int nShowCmd;} main_thread_args;DWORD WINAPI main_thread_start(LPVOID arg);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,		   LPWSTR lpCmdLine, int nShowCmd){    DWORD exit_code = 1;    main_thread_args args = {	hInstance, hPrevInstance, lpCmdLine, nShowCmd    };    HANDLE thread_h;    DWORD thread_id;    /* initialize everything */    GC_init();    /* start the main thread */    thread_h = GC_CreateThread(	NULL, 0, main_thread_start, &args, 0, &thread_id);    if (thread_h != NULL)    {	WaitForSingleObject (thread_h, INFINITE);	GetExitCodeThread (thread_h, &exit_code);	CloseHandle (thread_h);    }    GC_deinit();    DeleteCriticalSection(&GC_allocate_ml);    return (int) exit_code;}DWORD WINAPI main_thread_start(LPVOID arg){    main_thread_args * args = (main_thread_args *) arg;    return (DWORD) GC_WinMain (args->hInstance, args->hPrevInstance,			       args->lpCmdLine, args->nShowCmd);}# else /* !MSWINCE *//* Called by GC_init() - we hold the allocation lock.	*/void GC_thr_init(void) {    struct GC_stack_base sb;    int sb_result;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -