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

📄 alloc.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved. * Copyright (c) 1998 by Silicon Graphics.  All rights reserved. * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose,  provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * */# include "private/gc_priv.h"# include <stdio.h># if !defined(MACOS) && !defined(MSWINCE)#   include <signal.h>#   include <sys/types.h># endif/* * Separate free lists are maintained for different sized objects * up to MAXOBJBYTES. * The call GC_allocobj(i,k) ensures that the freelist for * kind k objects of size i points to a non-empty * free list. It returns a pointer to the first entry on the free list. * In a single-threaded world, GC_allocobj may be called to allocate * an object of (small) size i as follows: * *            opp = &(GC_objfreelist[i]); *            if (*opp == 0) GC_allocobj(i, NORMAL); *            ptr = *opp; *            *opp = obj_link(ptr); * * Note that this is very fast if the free list is non-empty; it should * only involve the execution of 4 or 5 simple instructions. * All composite objects on freelists are cleared, except for * their first word. *//* *  The allocator uses GC_allochblk to allocate large chunks of objects. * These chunks all start on addresses which are multiples of * HBLKSZ.   Each allocated chunk has an associated header, * which can be located quickly based on the address of the chunk. * (See headers.c for details.)  * This makes it possible to check quickly whether an * arbitrary address corresponds to an object administered by the * allocator. */word GC_non_gc_bytes = 0;  /* Number of bytes not intended to be collected */word GC_gc_no = 0;#ifndef SMALL_CONFIG  int GC_incremental = 0;  /* By default, stop the world.	*/#endifint GC_parallel = FALSE;   /* By default, parallel GC is off.	*/int GC_full_freq = 19;	   /* Every 20th collection is a full	*/			   /* collection, whether we need it 	*/			   /* or not.			        */GC_bool GC_need_full_gc = FALSE;			   /* Need full GC do to heap growth.	*/#ifdef THREADS  GC_bool GC_world_stopped = FALSE;# define IF_THREADS(x) x#else# define IF_THREADS(x)#endifword GC_used_heap_size_after_full = 0;char * GC_copyright[] ={"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ","Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved. ","Copyright (c) 1996-1998 by Silicon Graphics.  All rights reserved. ","Copyright (c) 1999-2001 by Hewlett-Packard Company.  All rights reserved. ","THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY"," EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.","See source code for details." };# include "version.h"/* some more variables */extern signed_word GC_bytes_found; /* Number of reclaimed bytes		*/				  /* after garbage collection      	*/GC_bool GC_dont_expand = 0;word GC_free_space_divisor = 3;extern GC_bool GC_collection_in_progress();		/* Collection is in progress, or was abandoned.	*/int GC_never_stop_func (void) { return(0); }unsigned long GC_time_limit = TIME_LIMIT;CLOCK_TYPE GC_start_time;  	/* Time at which we stopped world.	*/				/* used only in GC_timeout_stop_func.	*/int GC_n_attempts = 0;		/* Number of attempts at finishing	*/				/* collection within GC_time_limit.	*/#if defined(SMALL_CONFIG) || defined(NO_CLOCK)#   define GC_timeout_stop_func GC_never_stop_func#else  int GC_timeout_stop_func (void)  {    CLOCK_TYPE current_time;    static unsigned count = 0;    unsigned long time_diff;        if ((count++ & 3) != 0) return(0);    GET_TIME(current_time);    time_diff = MS_TIME_DIFF(current_time,GC_start_time);    if (time_diff >= GC_time_limit) {	if (GC_print_stats) {	    GC_log_printf("Abandoning stopped marking after ");	    GC_log_printf("%lu msecs", time_diff);	    GC_log_printf("(attempt %d)\n", GC_n_attempts);	}    	return(1);    }    return(0);  }#endif /* !SMALL_CONFIG *//* Return the minimum number of words that must be allocated between	*//* collections to amortize the collection cost.				*/static word min_bytes_allocd(){#   ifdef THREADS 	/* We punt, for now. */ 	signed_word stack_size = 10000;#   else        int dummy;        signed_word stack_size = (ptr_t)(&dummy) - GC_stackbottom;#   endif    word total_root_size;  	    /* includes double stack size,	*/    				    /* since the stack is expensive	*/    				    /* to scan.				*/    word scan_size;		/* Estimate of memory to be scanned 	*/				/* during normal GC.			*/        if (stack_size < 0) stack_size = -stack_size;    total_root_size = 2 * stack_size + GC_root_size;    scan_size = 2 * GC_composite_in_use + GC_atomic_in_use		+ total_root_size;    if (TRUE_INCREMENTAL) {        return scan_size / (2 * GC_free_space_divisor);    } else {        return scan_size / GC_free_space_divisor;    }}/* Return the number of bytes allocated, adjusted for explicit storage	*//* management, etc..  This number is used in deciding when to trigger	*//* collections.								*/word GC_adj_bytes_allocd(void){    signed_word result;    signed_word expl_managed =    		(signed_word)GC_non_gc_bytes		- (signed_word)GC_non_gc_bytes_at_gc;        /* Don't count what was explicitly freed, or newly allocated for	*/    /* explicit management.  Note that deallocating an explicitly	*/    /* managed object should not alter result, assuming the client	*/    /* is playing by the rules.						*/    result = (signed_word)GC_bytes_allocd    	     - (signed_word)GC_bytes_freed 	     + (signed_word)GC_finalizer_bytes_freed	     - expl_managed;    if (result > (signed_word)GC_bytes_allocd) {        result = GC_bytes_allocd;    	/* probably client bug or unfortunate scheduling */    }    result += GC_bytes_finalized;    	/* We count objects enqueued for finalization as though they	*/    	/* had been reallocated this round. Finalization is user	*/    	/* visible progress.  And if we don't count this, we have	*/    	/* stability problems for programs that finalize all objects.	*/    if (result < (signed_word)(GC_bytes_allocd >> 3)) {    	/* Always count at least 1/8 of the allocations.  We don't want	*/    	/* to collect too infrequently, since that would inhibit	*/    	/* coalescing of free storage blocks.				*/    	/* This also makes us partially robust against client bugs.	*/        return(GC_bytes_allocd >> 3);    } else {        return(result);    }}/* Clear up a few frames worth of garbage left at the top of the stack.	*//* This is used to prevent us from accidentally treating garbade left	*//* on the stack by other parts of the collector as roots.  This 	*//* differs from the code in misc.c, which actually tries to keep the	*//* stack clear of long-lived, client-generated garbage.			*/void GC_clear_a_few_frames(){#   define NWORDS 64    word frames[NWORDS];    int i;        for (i = 0; i < NWORDS; i++) frames[i] = 0;}/* Heap size at which we need a collection to avoid expanding past	*//* limits used by blacklisting.						*/static word GC_collect_at_heapsize = (word)(-1);/* Have we allocated enough to amortize a collection? */GC_bool GC_should_collect(void){    return(GC_adj_bytes_allocd() >= min_bytes_allocd()	   || GC_heapsize >= GC_collect_at_heapsize);}void GC_notify_full_gc(void){    if (GC_start_call_back != (void (*) (void))0) {	(*GC_start_call_back)();    }}GC_bool GC_is_full_gc = FALSE;/*  * Initiate a garbage collection if appropriate. * Choose judiciously * between partial, full, and stop-world collections. * Assumes lock held, signals disabled. */void GC_maybe_gc(void){    static int n_partial_gcs = 0;    if (GC_should_collect()) {        if (!GC_incremental) {            GC_gcollect_inner();            n_partial_gcs = 0;            return;        } else {#   	  ifdef PARALLEL_MARK	    GC_wait_for_reclaim();#   	  endif	  if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {	    if (GC_print_stats) {	        GC_log_printf(	          "***>Full mark for collection %lu after %ld allocd bytes\n",     		  (unsigned long)GC_gc_no+1,		  (long)GC_bytes_allocd);	    }	    GC_promote_black_lists();	    (void)GC_reclaim_all((GC_stop_func)0, TRUE);	    GC_clear_marks();            n_partial_gcs = 0;	    GC_notify_full_gc(); 	    GC_is_full_gc = TRUE;          } else {            n_partial_gcs++;          }	}        /* We try to mark with the world stopped.	*/        /* If we run out of time, this turns into	*/        /* incremental marking.			*/#	ifndef NO_CLOCK          if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }#	endif        if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED? 			    GC_never_stop_func : GC_timeout_stop_func)) {#           ifdef SAVE_CALL_CHAIN                GC_save_callers(GC_last_stack);#           endif            GC_finish_collection();        } else {	    if (!GC_is_full_gc) {		/* Count this as the first attempt */	        GC_n_attempts++;	    }	}    }}/* * Stop the world garbage collection.  Assumes lock held, signals disabled. * If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE. * Return TRUE if we successfully completed the collection. */GC_bool GC_try_to_collect_inner(GC_stop_func stop_func){    CLOCK_TYPE start_time, current_time;    if (GC_dont_gc) return FALSE;    if (GC_incremental && GC_collection_in_progress()) {      if (GC_print_stats) {	GC_log_printf(	    "GC_try_to_collect_inner: finishing collection in progress\n");      }      /* Just finish collection already in progress.	*/    	while(GC_collection_in_progress()) {    	    if (stop_func()) return(FALSE);    	    GC_collect_a_little_inner(1);    	}    }    if (stop_func == GC_never_stop_func) GC_notify_full_gc();    if (GC_print_stats) {        GET_TIME(start_time);	GC_log_printf(	   "Initiating full world-stop collection %lu after %ld allocd bytes\n",	   (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd);    }    GC_promote_black_lists();    /* Make sure all blocks have been reclaimed, so sweep routines	*/    /* don't see cleared mark bits.					*/    /* If we're guaranteed to finish, then this is unnecessary.		*/    /* In the find_leak case, we have to finish to guarantee that 	*/    /* previously unmarked objects are not reported as leaks.		*/#       ifdef PARALLEL_MARK	    GC_wait_for_reclaim();#       endif 	if ((GC_find_leak || stop_func != GC_never_stop_func)	    && !GC_reclaim_all(stop_func, FALSE)) {	    /* Aborted.  So far everything is still consistent.	*/	    return(FALSE);	}    GC_invalidate_mark_state();  /* Flush mark stack.	*/

⌨️ 快捷键说明

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