Beispiel #1
0
   void GC_register_data_segments(void)
   {
     struct Process     *proc;
     struct CommandLineInterface *cli;
     BPTR myseglist;
     ULONG *data;

#    ifdef __GNUC__
        ULONG dataSegSize;
        GC_bool found_segment = FALSE;
        extern char __data_size[];

        dataSegSize=__data_size+8;
        /* Can`t find the Location of __data_size, because
           it`s possible that is it, inside the segment. */

#     endif

        proc= (struct Process*)SysBase->ThisTask;

        /* Reference: Amiga Guru Book Pages: 538ff,565,573
                     and XOper.asm */
        myseglist = proc->pr_SegList;
        if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) {
          if (proc->pr_CLI != NULL) {
            /* ProcLoaded       'Loaded as a command: '*/
            cli = BADDR(proc->pr_CLI);
            myseglist = cli->cli_Module;
          }
        } else {
          ABORT("Not a Process.");
        }

        if (myseglist == NULL) {
            ABORT("Arrrgh.. can't find segments, aborting");
        }

        /* xoper hunks Shell Process */

        for (data = (ULONG *)BADDR(myseglist); data != NULL;
             data = (ULONG *)BADDR(data[0])) {
          if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
              ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
#             ifdef __GNUC__
                if (dataSegSize == data[-1]) {
                  found_segment = TRUE;
                }
#             endif
              GC_add_roots_inner((char *)&data[1],
                                 ((char *)&data[1]) + data[-1], FALSE);
          }
        } /* for */
#       ifdef __GNUC__
           if (!found_segment) {
             ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
           }
#       endif
   }
Beispiel #2
0
GC_API void GC_CALL GC_add_roots(void *b, void *e)
{
    DCL_LOCK_STATE;

    if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
    LOCK();
    GC_add_roots_inner((ptr_t)b, (ptr_t)e, FALSE);
    UNLOCK();
}
Beispiel #3
0
/* We hold the allocation lock.	*/
void GC_thr_init(void)
{
#   ifndef GC_DARWIN_THREADS
        int dummy;
#   endif
    GC_thread t;

    if (GC_thr_initialized) return;
    GC_thr_initialized = TRUE;
    
#   ifdef HANDLE_FORK
      /* Prepare for a possible fork.	*/
        pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
	  	       GC_fork_child_proc);
#   endif /* HANDLE_FORK */
#   if defined(INCLUDE_LINUX_THREAD_DESCR)
      /* Explicitly register the region including the address 		*/
      /* of a thread local variable.  This should include thread	*/
      /* locals for the main thread, except for those allocated		*/
      /* in response to dlopen calls.					*/  
	{
	  ptr_t thread_local_addr = (ptr_t)(&dummy_thread_local);
	  ptr_t main_thread_start, main_thread_end;
          if (!GC_enclosing_mapping(thread_local_addr, &main_thread_start,
				    &main_thread_end)) {
	    ABORT("Failed to find mapping for main thread thread locals");
	  }
	  GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);
	}
#   endif
    /* Add the initial thread, so we can stop it.	*/
      t = GC_new_thread(pthread_self());
#     ifdef GC_DARWIN_THREADS
         t -> stop_info.mach_thread = mach_thread_self();
#     else
         t -> stop_info.stack_ptr = (ptr_t)(&dummy);
#     endif
      t -> flags = DETACHED | MAIN_THREAD;

    GC_stop_init();

    /* Set GC_nprocs.  */
      {
	char * nprocs_string = GETENV("GC_NPROCS");
	GC_nprocs = -1;
	if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
      }
      if (GC_nprocs <= 0) {
#       if defined(GC_HPUX_THREADS)
	  GC_nprocs = pthread_num_processors_np();
#       endif
#	if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \
	   || defined(GC_SOLARIS_THREADS) || defined(GC_GNU_THREADS)
	  GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
	  if (GC_nprocs <= 0) GC_nprocs = 1;
#	endif
#       if defined(GC_IRIX_THREADS)
	  GC_nprocs = sysconf(_SC_NPROC_ONLN);
	  if (GC_nprocs <= 0) GC_nprocs = 1;
#       endif
#       if defined(GC_NETBSD_THREADS)
	  GC_nprocs = get_ncpu();
#       endif
#       if defined(GC_OPENBSD_THREADS)
	  GC_nprocs = 1;
#       endif
#       if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
	  int ncpus = 1;
	  size_t len = sizeof(ncpus);
	  sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
Beispiel #4
0
    /* xoper hunks Shell Process */

    num=0;
    for (data = (ULONG *)BADDR(myseglist); data != NULL;
            data = (ULONG *)BADDR(data[0])) {
        if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
                ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
#             ifdef __GNUC__
            if (dataSegSize == data[-1]) {
                found_segment = TRUE;
            }
# 	      endif
            GC_add_roots_inner((char *)&data[1],
                               ((char *)&data[1]) + data[-1], FALSE);
        }
        ++num;
    } /* for */
# 	ifdef __GNUC__
    if (!found_segment) {
        ABORT("Can`t find correct Segments.\nSolution: Use an newer version of ixemul.library");
    }
# 	endif
}

#if 0 /* old version */
void GC_register_data_segments()
{
    extern struct WBStartup *_WBenchMsg;
    struct Process	*proc;
    struct CommandLineInterface *cli;
    BPTR myseglist;
    ULONG *data;

    if ( _WBenchMsg != 0 ) {
        if ((myseglist = _WBenchMsg->sm_Segment) == 0) {
            GC_err_puts("No seglist from workbench\n");
            return;
        }
    } else {
        if ((proc = (struct Process *)FindTask(0)) == 0) {
            GC_err_puts("Cannot find process structure\n");
            return;
        }
        if ((cli = BADDR(proc->pr_CLI)) == 0) {
            GC_err_puts("No CLI\n");
            return;
        }
        if ((myseglist = cli->cli_Module) == 0) {
            GC_err_puts("No seglist from CLI\n");
            return;
        }
    }

    for (data = (ULONG *)BADDR(myseglist); data != 0;
            data = (ULONG *)BADDR(data[0])) {
#        ifdef AMIGA_SKIP_SEG
        if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) ||
                ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) {
#	 else
        {
#	 endif /* AMIGA_SKIP_SEG */
            GC_add_roots_inner((char *)&data[1],
            ((char *)&data[1]) + data[-1], FALSE);
        }
    }
}
#endif /* old version */


#endif



#ifdef GC_AMIGA_AM

#ifndef GC_AMIGA_FASTALLOC

void *GC_amiga_allocwrapper(size_t size,void *(*AllocFunction)(size_t size2)) {
    return (*AllocFunction)(size);
}

void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
    =GC_amiga_allocwrapper;

#else




void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2));

void *(*GC_amiga_allocwrapper_do)(size_t size,void *(*AllocFunction)(size_t size2))
    =GC_amiga_allocwrapper_firsttime;


/******************************************************************
   Amiga-spesific routines to obtain memory, and force GC to give
   back fast-mem whenever possible.
	These hacks makes gc-programs go many times faster when
   the amiga is low on memory, and are therefore strictly necesarry.

   -Kjetil S. Matheussen, 2000.
******************************************************************/



/* List-header for all allocated memory. */

struct GC_Amiga_AllocedMemoryHeader {
    ULONG size;
    struct GC_Amiga_AllocedMemoryHeader *next;
};
struct GC_Amiga_AllocedMemoryHeader *GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(int)~(NULL);



/* Type of memory. Once in the execution of a program, this might change to MEMF_ANY|MEMF_CLEAR */

ULONG GC_AMIGA_MEMF = MEMF_FAST | MEMF_CLEAR;


/* Prevents GC_amiga_get_mem from allocating memory if this one is TRUE. */
#ifndef GC_AMIGA_ONLYFAST
BOOL GC_amiga_dontalloc=FALSE;
#endif

#ifdef GC_AMIGA_PRINTSTATS
int succ=0,succ2=0;
int nsucc=0,nsucc2=0;
int nullretries=0;
int numcollects=0;
int chipa=0;
int allochip=0;
int allocfast=0;
int cur0=0;
int cur1=0;
int cur10=0;
int cur50=0;
int cur150=0;
int cur151=0;
int ncur0=0;
int ncur1=0;
int ncur10=0;
int ncur50=0;
int ncur150=0;
int ncur151=0;
#endif

/* Free everything at program-end. */

void GC_amiga_free_all_mem(void) {
    struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM));
    struct GC_Amiga_AllocedMemoryHeader *temp;

#ifdef GC_AMIGA_PRINTSTATS
    printf("\n\n"
           "%d bytes of chip-mem, and %d bytes of fast-mem where allocated from the OS.\n",
           allochip,allocfast
          );
    printf(
        "%d bytes of chip-mem were returned from the GC_AMIGA_FASTALLOC supported allocating functions.\n",
        chipa
    );
    printf("\n");
    printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects);
    printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries);
    printf("\n");
    printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2);
    printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2);
    printf("\n");
    printf(
        "Number of retries before succeding a chip->fast force:\n"
        "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
        cur0,cur1,cur10,cur50,cur150,cur151
    );
    printf(
        "Number of retries before giving up a chip->fast force:\n"
        "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n",
        ncur0,ncur1,ncur10,ncur50,ncur150,ncur151
    );
#endif

    while(gc_am!=NULL) {
        temp=gc_am->next;
        FreeMem(gc_am,gc_am->size);
        gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp));
    }
}

#ifndef GC_AMIGA_ONLYFAST

/* All memory with address lower than this one is chip-mem. */

char *chipmax;


/*
 * Allways set to the last size of memory tried to be allocated.
 * Needed to ensure allocation when the size is bigger than 100000.
 *
 */
size_t latestsize;

#endif


/*
 * The actual function that is called with the GET_MEM macro.
 *
 */

void *GC_amiga_get_mem(size_t size) {
    struct GC_Amiga_AllocedMemoryHeader *gc_am;

#ifndef GC_AMIGA_ONLYFAST
    if(GC_amiga_dontalloc==TRUE) {
//		printf("rejected, size: %d, latestsize: %d\n",size,latestsize);
        return NULL;
    }

    // We really don't want to use chip-mem, but if we must, then as little as possible.
    if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL;
#endif

    gc_am=AllocMem((ULONG)(size + sizeof(struct GC_Amiga_AllocedMemoryHeader)),GC_AMIGA_MEMF);
    if(gc_am==NULL) return NULL;

    gc_am->next=GC_AMIGAMEM;
    gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader);
    GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am));

//	printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize);

#ifdef GC_AMIGA_PRINTSTATS
    if((char *)gc_am<chipmax) {
        allochip+=size;
    } else {
        allocfast+=size;
    }
#endif

    return gc_am+1;

}




#ifndef GC_AMIGA_ONLYFAST

/* Tries very hard to force GC to find fast-mem to return. Done recursively
 * to hold the rejected memory-pointers reachable from the collector in an
 * easy way.
 *
 */
#ifdef GC_AMIGA_RETRY
void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const int rec) {
    void *ret;

    ret=(*AllocFunction)(size);

#ifdef GC_AMIGA_PRINTSTATS
    if((char *)ret>chipmax || ret==NULL) {
        if(ret==NULL) {
            nsucc++;
            nsucc2+=size;
            if(rec==0) ncur0++;
            if(rec==1) ncur1++;
            if(rec>1 && rec<10) ncur10++;
            if(rec>=10 && rec<50) ncur50++;
            if(rec>=50 && rec<150) ncur150++;
            if(rec>=150) ncur151++;
        } else {
            succ++;
            succ2+=size;
            if(rec==0) cur0++;
            if(rec==1) cur1++;
            if(rec>1 && rec<10) cur10++;
            if(rec>=10 && rec<50) cur50++;
            if(rec>=50 && rec<150) cur150++;
            if(rec>=150) cur151++;
        }
    }
#endif

    if (((char *)ret)<=chipmax && ret!=NULL && (rec<(size>500000?9:size/5000))) {
        ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1);
//		GC_free(ret2);
    }

    return ret;
}
Beispiel #5
0
  /* this function is called repeatedly by GC_register_map_entries.     */
  GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e)
  {
    int i;
    GC_bool rebuild = FALSE;

    GC_ASSERT(I_HOLD_LOCK());
    GC_ASSERT((word)b % sizeof(word) == 0 && (word)e % sizeof(word) == 0);
    for (i = 0; i < n_root_sets; i++) {
      ptr_t r_start, r_end;

      if (GC_static_roots[i].r_tmp) {
        /* The remaining roots are skipped as they are all temporary. */
#       ifdef GC_ASSERTIONS
          int j;
          for (j = i + 1; j < n_root_sets; j++) {
            GC_ASSERT(GC_static_roots[j].r_tmp);
          }
#       endif
        break;
      }
      r_start = GC_static_roots[i].r_start;
      r_end = GC_static_roots[i].r_end;
      if (!EXPECT((word)e <= (word)r_start || (word)r_end <= (word)b, TRUE)) {
#       ifdef DEBUG_ADD_DEL_ROOTS
          GC_log_printf("Removing %p .. %p from root section %d (%p .. %p)\n",
                        (void *)b, (void *)e,
                        i, (void *)r_start, (void *)r_end);
#       endif
        if ((word)r_start < (word)b) {
          GC_root_size -= r_end - b;
          GC_static_roots[i].r_end = b;
          /* No need to rebuild as hash does not use r_end value. */
          if ((word)e < (word)r_end) {
            int j;

            if (rebuild) {
              GC_rebuild_root_index();
              rebuild = FALSE;
            }
            GC_add_roots_inner(e, r_end, FALSE); /* updates n_root_sets */
            for (j = i + 1; j < n_root_sets; j++)
              if (GC_static_roots[j].r_tmp)
                break;
            if (j < n_root_sets-1 && !GC_static_roots[n_root_sets-1].r_tmp) {
              /* Exchange the roots to have all temporary ones at the end. */
              ptr_t tmp_r_start = GC_static_roots[j].r_start;
              ptr_t tmp_r_end = GC_static_roots[j].r_end;

              GC_static_roots[j].r_start =
                                GC_static_roots[n_root_sets-1].r_start;
              GC_static_roots[j].r_end = GC_static_roots[n_root_sets-1].r_end;
              GC_static_roots[j].r_tmp = FALSE;
              GC_static_roots[n_root_sets-1].r_start = tmp_r_start;
              GC_static_roots[n_root_sets-1].r_end = tmp_r_end;
              GC_static_roots[n_root_sets-1].r_tmp = TRUE;
              rebuild = TRUE;
            }
          }
        } else {
          if ((word)e < (word)r_end) {
            GC_root_size -= e - r_start;
            GC_static_roots[i].r_start = e;
          } else {
            GC_remove_root_at_pos(i);
            i--;
          }
          rebuild = TRUE;
        }
      }
    }
    if (rebuild)
      GC_rebuild_root_index();
  }