Example #1
0
  /* Turn on GC_win32_dll_threads	*/
  GC_API void GC_use_DllMain(void)
  {
#     ifdef THREAD_LOCAL_ALLOC
	  ABORT("Cannot use thread local allocation with DllMain-based "
		"thread registration.");
	  /* Thread-local allocation really wants to lock at thread	*/
	  /* entry and exit.						*/
#     endif
      GC_ASSERT(!parallel_initialized);
      GC_win32_dll_threads = TRUE;
      GC_init_parallel();
  }
Example #2
0
int GC_pthread_join(pthread_t pthread_id, void **retval) {
    int result;
    int i;
    GC_thread joinee;

#   if DEBUG_CYGWIN_THREADS
      GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",
		(int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);
#   endif
#   if DEBUG_WIN32_PTHREADS
      GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",
		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
#   endif

    if (!parallel_initialized) GC_init_parallel();
    /* Thread being joined might not have registered itself yet. */
    /* After the join,thread id may have been recycled.		 */
    /* FIXME: It would be better if this worked more like	 */
    /* pthread_support.c.					 */

    #ifndef GC_WIN32_PTHREADS
      while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10);
    #endif

    result = pthread_join(pthread_id, retval);

    #ifdef GC_WIN32_PTHREADS
      /* win32_pthreads id are unique */
      joinee = GC_lookup_pthread(pthread_id);
    #endif

    if (!GC_win32_dll_threads) {
      LOCK();
      GC_delete_gc_thread(joinee);
      UNLOCK();
    } /* otherwise dllmain handles it.	*/

#   if DEBUG_CYGWIN_THREADS
      GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
		 (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);
#   endif
#   if DEBUG_WIN32_PTHREADS
      GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);
#   endif

    return result;
}
Example #3
0
GC_PTR GC_local_malloc(size_t bytes)
{
    if (EXPECT(!SMALL_ENOUGH(bytes),0)) {
        return(GC_malloc(bytes));
    } else {
	int index = INDEX_FROM_BYTES(bytes);
	ptr_t * my_fl;
	ptr_t my_entry;
#	if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
	GC_key_t k = GC_thread_key;
#	endif
	void * tsd;

#	if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
	    if (EXPECT(0 == k, 0)) {
		/* This can happen if we get called when the world is	*/
		/* being initialized.  Whether we can actually complete	*/
		/* the initialization then is unclear.			*/
		GC_init_parallel();
		k = GC_thread_key;
	    }
#	endif
	tsd = GC_getspecific(GC_thread_key);
#	ifdef GC_ASSERTIONS
	  LOCK();
	  GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self()));
	  UNLOCK();
#	endif
	my_fl = ((GC_thread)tsd) -> normal_freelists + index;
	my_entry = *my_fl;
	if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
	    ptr_t next = obj_link(my_entry);
	    GC_PTR result = (GC_PTR)my_entry;
	    *my_fl = next;
	    obj_link(my_entry) = 0;
	    PREFETCH_FOR_WRITE(next);
	    return result;
	} else if ((word)my_entry - 1 < DIRECT_GRANULES) {
	    *my_fl = my_entry + index + 1;
            return GC_malloc(bytes);
	} else {
	    GC_generic_malloc_many(BYTES_FROM_INDEX(index), NORMAL, my_fl);
	    if (*my_fl == 0) return GC_oom_fn(bytes);
	    return GC_local_malloc(bytes);
	}
    }
}
Example #4
0
/* Cygwin-pthreads calls CreateThread internally, but it's not
 * easily interceptible by us..
 *   so intercept pthread_create instead
 */
int
GC_pthread_create(pthread_t *new_thread,
		  const pthread_attr_t *attr,
                  void *(*start_routine)(void *), void *arg) {
    int result;
    struct start_info * si;

    if (!parallel_initialized) GC_init_parallel();
    		/* make sure GC is initialized (i.e. main thread is attached) */
    if (GC_win32_dll_threads) {
      return pthread_create(new_thread, attr, start_routine, arg);
    }
    
    /* This is otherwise saved only in an area mmapped by the thread */
    /* library, which isn't visible to the collector.		 */
    si = GC_malloc_uncollectable(sizeof(struct start_info)); 
    if (0 == si) return(EAGAIN);

    si -> start_routine = start_routine;
    si -> arg = arg;
    if (attr != 0 &&
        pthread_attr_getdetachstate(attr, &si->detached)
	== PTHREAD_CREATE_DETACHED) {
      si->detached = TRUE;
    }

#   if DEBUG_CYGWIN_THREADS
      GC_printf("About to create a thread from 0x%x(0x%x)\n",
		(int)pthread_self(), GetCurrentThreadId);
#   endif
#   if DEBUG_WIN32_PTHREADS
      GC_printf("About to create a thread from 0x%x(0x%x)\n",
		(int)(pthread_self()).p, GetCurrentThreadId());
#   endif
    GC_need_to_lock = TRUE;
    result = pthread_create(new_thread, attr, GC_pthread_start, si); 

    if (result) { /* failure */
      	GC_free(si);
    } 

    return(result);
}
Example #5
0
int GC_pthread_detach(pthread_t thread)
{
    int result;
    GC_thread thread_gc_id;
    
    if (!parallel_initialized) GC_init_parallel();
    LOCK();
    thread_gc_id = GC_lookup_pthread(thread);
    UNLOCK();
    result = pthread_detach(thread);
    if (result == 0) {
      LOCK();
      thread_gc_id -> flags |= DETACHED;
      /* Here the pthread thread id may have been recycled. */
      if (thread_gc_id -> flags & FINISHED) {
        GC_delete_gc_thread(thread_gc_id);
      }
      UNLOCK();
    }
    return result;
}
Example #6
0
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;
    }
}
Example #7
0
uintptr_t GC_beginthreadex(
    void *security, unsigned stack_size,
    unsigned ( __stdcall *start_address )( void * ),
    void *arglist, unsigned initflag, unsigned *thrdaddr)
{
    uintptr_t thread_h;

    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)(-1L);
      }

      /* 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;
    }
}
Example #8
0
/* nothing required here... */
int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) {
  if (!parallel_initialized) GC_init_parallel();
  return pthread_sigmask(how, set, oset);
}