[BACK]Return to win32_threads.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/win32_threads.c, Revision 1.1

1.1     ! noro        1: #ifdef WIN32_THREADS
        !             2:
        !             3: #include "gc_priv.h"
        !             4:
        !             5: #define STRICT
        !             6: #include <windows.h>
        !             7:
        !             8: #define MAX_THREADS 64
        !             9:
        !            10: struct thread_entry {
        !            11:   LONG in_use;
        !            12:   DWORD id;
        !            13:   HANDLE handle;
        !            14:   void *stack;         /* The cold end of the stack.   */
        !            15:                        /* 0 ==> entry not valid.       */
        !            16:                        /* !in_use ==> stack == 0       */
        !            17:   CONTEXT context;
        !            18:   GC_bool suspended;
        !            19: };
        !            20:
        !            21: volatile GC_bool GC_please_stop = FALSE;
        !            22:
        !            23: volatile struct thread_entry thread_table[MAX_THREADS];
        !            24:
        !            25: void GC_stop_world()
        !            26: {
        !            27:   DWORD thread_id = GetCurrentThreadId();
        !            28:   int i;
        !            29:
        !            30:   GC_please_stop = TRUE;
        !            31:   for (i = 0; i < MAX_THREADS; i++)
        !            32:     if (thread_table[i].stack != 0
        !            33:        && thread_table[i].id != thread_id) {
        !            34:       if (SuspendThread(thread_table[i].handle) == (DWORD)-1)
        !            35:        ABORT("SuspendThread failed");
        !            36:       thread_table[i].suspended = TRUE;
        !            37:     }
        !            38: }
        !            39:
        !            40: void GC_start_world()
        !            41: {
        !            42:   DWORD thread_id = GetCurrentThreadId();
        !            43:   int i;
        !            44:   for (i = 0; i < MAX_THREADS; i++)
        !            45:     if (thread_table[i].stack != 0 && thread_table[i].suspended
        !            46:        && thread_table[i].id != thread_id) {
        !            47:       if (ResumeThread(thread_table[i].handle) == (DWORD)-1)
        !            48:        ABORT("ResumeThread failed");
        !            49:       thread_table[i].suspended = FALSE;
        !            50:     }
        !            51:   GC_please_stop = FALSE;
        !            52: }
        !            53:
        !            54: ptr_t GC_current_stackbottom()
        !            55: {
        !            56:   DWORD thread_id = GetCurrentThreadId();
        !            57:   int i;
        !            58:   for (i = 0; i < MAX_THREADS; i++)
        !            59:     if (thread_table[i].stack && thread_table[i].id == thread_id)
        !            60:       return thread_table[i].stack;
        !            61:   ABORT("no thread table entry for current thread");
        !            62: }
        !            63:
        !            64: ptr_t GC_get_lo_stack_addr(ptr_t s)
        !            65: {
        !            66:     ptr_t bottom;
        !            67:     MEMORY_BASIC_INFORMATION info;
        !            68:     VirtualQuery(s, &info, sizeof(info));
        !            69:     do {
        !            70:        bottom = info.BaseAddress;
        !            71:        VirtualQuery(bottom - 1, &info, sizeof(info));
        !            72:     } while ((info.Protect & PAGE_READWRITE) && !(info.Protect & PAGE_GUARD));
        !            73:     return(bottom);
        !            74: }
        !            75:
        !            76: void GC_push_all_stacks()
        !            77: {
        !            78:   DWORD thread_id = GetCurrentThreadId();
        !            79:   int i;
        !            80:   for (i = 0; i < MAX_THREADS; i++)
        !            81:     if (thread_table[i].stack) {
        !            82:       ptr_t bottom = GC_get_lo_stack_addr(thread_table[i].stack);
        !            83:       if (thread_table[i].id == thread_id)
        !            84:        GC_push_all(&i, thread_table[i].stack);
        !            85:       else {
        !            86:        thread_table[i].context.ContextFlags
        !            87:                        = (CONTEXT_INTEGER|CONTEXT_CONTROL);
        !            88:        if (!GetThreadContext(thread_table[i].handle,
        !            89:                              &thread_table[i].context))
        !            90:          ABORT("GetThreadContext failed");
        !            91:        if (thread_table[i].context.Esp >= (DWORD)thread_table[i].stack
        !            92:            || thread_table[i].context.Esp < (DWORD)bottom)
        !            93:            ABORT("Thread stack pointer out of range");
        !            94:        GC_push_one ((word) thread_table[i].context.Edi);
        !            95:        GC_push_one ((word) thread_table[i].context.Esi);
        !            96:        GC_push_one ((word) thread_table[i].context.Ebx);
        !            97:        GC_push_one ((word) thread_table[i].context.Edx);
        !            98:        GC_push_one ((word) thread_table[i].context.Ecx);
        !            99:        GC_push_one ((word) thread_table[i].context.Eax);
        !           100:        GC_push_all_stack(thread_table[i].context.Esp, thread_table[i].stack);
        !           101:       }
        !           102:     }
        !           103: }
        !           104:
        !           105: void GC_get_next_stack(char *start, char **lo, char **hi)
        !           106: {
        !           107:     int i;
        !           108: #   define ADDR_LIMIT (char *)(-1L)
        !           109:     char * current_min = ADDR_LIMIT;
        !           110:
        !           111:     for (i = 0; i < MAX_THREADS; i++) {
        !           112:        char * s = (char *)thread_table[i].stack;
        !           113:
        !           114:        if (0 != s && s > start && s < current_min) {
        !           115:            current_min = s;
        !           116:        }
        !           117:     }
        !           118:     *hi = current_min;
        !           119:     if (current_min == ADDR_LIMIT) {
        !           120:        *lo = ADDR_LIMIT;
        !           121:        return;
        !           122:     }
        !           123:     *lo = GC_get_lo_stack_addr(current_min);
        !           124:     if (*lo < start) *lo = start;
        !           125: }
        !           126:
        !           127: LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
        !           128:
        !           129: /*
        !           130:  * This isn't generally safe, since DllMain is not premptible.
        !           131:  * If another thread holds the lock while this runs we're in trouble.
        !           132:  * Pontus Rydin suggests wrapping the thread start routine instead.
        !           133:  */
        !           134: BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
        !           135: {
        !           136:   switch (reason) {
        !           137:   case DLL_PROCESS_ATTACH:
        !           138:     InitializeCriticalSection(&GC_allocate_ml);
        !           139:     GC_init(); /* Force initialization before thread attach.   */
        !           140:     /* fall through */
        !           141:   case DLL_THREAD_ATTACH:
        !           142:     {
        !           143:       int i;
        !           144:       /* It appears to be unsafe to acquire a lock here, since this    */
        !           145:       /* code is apparently not preeemptible on some systems.          */
        !           146:       /* (This is based on complaints, not on Microsoft's official     */
        !           147:       /* documentation, which says this should perform "only simple    */
        !           148:       /* inititalization tasks".)                                      */
        !           149:       /* Hence we make do with nonblocking synchronization.            */
        !           150:
        !           151:       /* The following should be a noop according to the win32 */
        !           152:       /* documentation.  There is empirical evidence that it   */
        !           153:       /* isn't.                - HB                                    */
        !           154: #     ifndef SMALL_CONFIG
        !           155:        if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
        !           156: #     endif
        !           157:
        !           158:       for (i = 0; InterlockedExchange(&thread_table[i].in_use,1) != 0; i++) {
        !           159:        /* Compare-and-swap would make this cleaner, but that's not     */
        !           160:        /* supported before Windows 98 and NT 4.0.  In Windows 2000,    */
        !           161:        /* InterlockedExchange is supposed to be replaced by            */
        !           162:        /* InterlockedExchangePointer, but that's not really what I     */
        !           163:        /* want here.                                                   */
        !           164:        if (i == MAX_THREADS - 1)
        !           165:          ABORT("too many threads");
        !           166:       }
        !           167:       thread_table[i].id = GetCurrentThreadId();
        !           168:       if (!DuplicateHandle(GetCurrentProcess(),
        !           169:                           GetCurrentThread(),
        !           170:                           GetCurrentProcess(),
        !           171:                           &thread_table[i].handle,
        !           172:                           0,
        !           173:                           0,
        !           174:                           DUPLICATE_SAME_ACCESS)) {
        !           175:            DWORD last_error = GetLastError();
        !           176:            GC_printf1("Last error code: %lx\n", last_error);
        !           177:            ABORT("DuplicateHandle failed");
        !           178:       }
        !           179:       thread_table[i].stack = GC_get_stack_base();
        !           180:       /* If this thread is being created while we are trying to stop   */
        !           181:       /* the world, wait here.  Hopefully this can't happen on any     */
        !           182:       /* systems that don't allow us to block here.                    */
        !           183:       while (GC_please_stop) Sleep(20);
        !           184:     }
        !           185:     break;
        !           186:   case DLL_PROCESS_DETACH:
        !           187:   case DLL_THREAD_DETACH:
        !           188:     {
        !           189:       int i;
        !           190:       DWORD thread_id = GetCurrentThreadId();
        !           191:       LOCK();
        !           192:       for (i = 0;
        !           193:            thread_table[i].stack == 0 || thread_table[i].id != thread_id;
        !           194:           i++) {
        !           195:        if (i == MAX_THREADS - 1)
        !           196:          ABORT("thread not found on detach");
        !           197:       }
        !           198:       thread_table[i].stack = 0;
        !           199:       thread_table[i].in_use = FALSE;
        !           200:       CloseHandle(thread_table[i].handle);
        !           201:       BZERO(&thread_table[i].context, sizeof(CONTEXT));
        !           202:       UNLOCK();
        !           203:     }
        !           204:     break;
        !           205:   }
        !           206:   return TRUE;
        !           207: }
        !           208:
        !           209: #endif /* WIN32_THREADS */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>