Ejemplo n.º 1
0
void * GC_mark_thread(void * id)
{
  word my_mark_no = 0;

  marker_sp[(word)id] = GC_approx_sp();
# ifdef IA64
    marker_bsp[(word)id] = GC_save_regs_in_stack();
# endif
  for (;; ++my_mark_no) {
    /* GC_mark_no is passed only to allow GC_help_marker to terminate	*/
    /* promptly.  This is important if it were called from the signal	*/
    /* handler or from the GC lock acquisition code.  Under Linux, it's	*/
    /* not safe to call it from a signal handler, since it uses mutexes	*/
    /* and condition variables.  Since it is called only here, the 	*/
    /* argument is unnecessary.						*/
    if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) {
	/* resynchronize if we get far off, e.g. because GC_mark_no	*/
	/* wrapped.							*/
	my_mark_no = GC_mark_no;
    }
#   ifdef DEBUG_THREADS
	GC_printf("Starting mark helper for mark number %lu\n", my_mark_no);
#   endif
    GC_help_marker(my_mark_no);
  }
}
Ejemplo n.º 2
0
/* ctxt is either a pointer to a ucontext_t we generated, or NULL.	*/
void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
				 ptr_t arg)
{
    word dummy;
    void * context = 0;

#   if defined(HAVE_PUSH_REGS)
      GC_push_regs();
#   elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32)
      /* Older versions of Darwin seem to lack getcontext(). */
      /* ARM Linux often doesn't support a real getcontext(). */
      ucontext_t ctxt;
      if (getcontext(&ctxt) < 0)
	ABORT ("Getcontext failed: Use another register retrieval method?");
      context = &ctxt;
#     if defined(SPARC) || defined(IA64)
        /* On a register window machine, we need to save register	*/
        /* contents on the stack for this to work.  This may already be	*/
        /* subsumed by the getcontext() call.				*/
        {
          GC_save_regs_ret_val = GC_save_regs_in_stack();
        }
#     endif /* register windows. */
#   elif defined(HAVE_BUILTIN_UNWIND_INIT)
      /* This was suggested by Richard Henderson as the way to	*/
      /* force callee-save registers and register windows onto	*/
      /* the stack.						*/
      __builtin_unwind_init();
#   else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE  */
         /* && !HAVE_PUSH_REGS			     */
        /* Generic code                          */
        /* The idea is due to Parag Patel at HP. */
        /* We're not sure whether he would like  */
        /* to be he acknowledged for it or not.  */
        jmp_buf regs;
        register word * i = (word *) regs;
        register ptr_t lim = (ptr_t)(regs) + (sizeof regs);

        /* Setjmp doesn't always clear all of the buffer.		*/
        /* That tends to preserve garbage.  Clear it.   		*/
	for (; (char *)i < lim; i++) {
	    *i = 0;
	}
#       if defined(MSWIN32) || defined(MSWINCE) \
                  || defined(UTS4) || defined(LINUX) || defined(EWS4800)
	  (void) setjmp(regs);
#       else
          (void) _setjmp(regs);
	  /* We don't want to mess with signals. According to	*/
	  /* SUSV3, setjmp() may or may not save signal mask.	*/
	  /* _setjmp won't, but is less portable.		*/
#       endif
#   endif /* !HAVE_PUSH_REGS ... */
    fn(arg, context);
    /* Strongly discourage the compiler from treating the above	*/
    /* as a tail-call, since that would pop the register 	*/
    /* contents before we get a chance to look at them.		*/
    GC_noop1((word)(&dummy));
}