LCOV - code coverage report
Current view: top level - mm/boehm-gc - fnlz_mlc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 68 0.0 %
Date: 2017-07-14 10:03:36 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2011 by Hewlett-Packard Company.  All rights reserved.
       3             :  *
       4             :  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
       5             :  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
       6             :  *
       7             :  * Permission is hereby granted to use or copy this program
       8             :  * for any purpose,  provided the above notices are retained on all copies.
       9             :  * Permission to modify the code and to distribute modified code is granted,
      10             :  * provided the above notices are retained, and a notice that the code was
      11             :  * modified is included with the above copyright notice.
      12             :  *
      13             :  */
      14             : 
      15             : #include "private/gc_priv.h"
      16             : 
      17             : #ifdef ENABLE_DISCLAIM
      18             : 
      19             : #include "gc_disclaim.h"
      20             : 
      21             : #ifdef THREAD_LOCAL_ALLOC
      22             : # include "private/thread_local_alloc.h"
      23             : #else
      24             :   STATIC ptr_t * GC_finalized_objfreelist = NULL;
      25             : #endif /* !THREAD_LOCAL_ALLOC */
      26             : 
      27             : STATIC int GC_finalized_kind = 0;
      28             : 
      29           0 : STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
      30             : {
      31           0 :     word fc_word = *(word *)obj;
      32             : 
      33           0 :     if ((fc_word & 1) != 0) {
      34             :        /* The disclaim function may be passed fragments from the        */
      35             :        /* free-list, on which it should not run finalization.           */
      36             :        /* To recognize this case, we use the fact that the first word   */
      37             :        /* on such fragments are always even (a link to the next         */
      38             :        /* fragment, or NULL).  If it is desirable to have a finalizer   */
      39             :        /* which does not use the first word for storing finalization    */
      40             :        /* info, GC_reclaim_with_finalization must be extended to clear  */
      41             :        /* fragments so that the assumption holds for the selected word. */
      42           0 :         const struct GC_finalizer_closure *fc = (void *)(fc_word & ~(word)1);
      43           0 :         (*fc->proc)((word *)obj + 1, fc->cd);
      44             :     }
      45           0 :     return 0;
      46             : }
      47             : 
      48             : static GC_bool done_init = FALSE;
      49             : 
      50           0 : GC_API void GC_CALL GC_init_finalized_malloc(void)
      51             : {
      52             :     DCL_LOCK_STATE;
      53             : 
      54           0 :     GC_init();  /* In case it's not already done.       */
      55           0 :     LOCK();
      56           0 :     if (done_init) {
      57           0 :         UNLOCK();
      58           0 :         return;
      59             :     }
      60           0 :     done_init = TRUE;
      61             : 
      62             :     /* The finalizer closure is placed in the first word in order to    */
      63             :     /* use the lower bits to distinguish live objects from objects on   */
      64             :     /* the free list.  The downside of this is that we need one-word    */
      65             :     /* offset interior pointers, and that GC_base does not return the   */
      66             :     /* start of the user region.                                        */
      67           0 :     GC_register_displacement_inner(sizeof(word));
      68             : 
      69           0 :     GC_finalized_objfreelist = (ptr_t *)GC_new_free_list_inner();
      70           0 :     GC_finalized_kind = GC_new_kind_inner((void **)GC_finalized_objfreelist,
      71             :                                           GC_DS_LENGTH, TRUE, TRUE);
      72           0 :     GC_register_disclaim_proc(GC_finalized_kind, GC_finalized_disclaim, TRUE);
      73           0 :     UNLOCK();
      74             : }
      75             : 
      76           0 : GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
      77             :                                               int mark_unconditionally)
      78             : {
      79             :     GC_ASSERT((unsigned)kind < MAXOBJKINDS);
      80           0 :     GC_obj_kinds[kind].ok_disclaim_proc = proc;
      81           0 :     GC_obj_kinds[kind].ok_mark_unconditionally = (GC_bool)mark_unconditionally;
      82           0 : }
      83             : 
      84             : #ifdef THREAD_LOCAL_ALLOC
      85           0 :   STATIC void * GC_core_finalized_malloc(size_t lb,
      86             :                                 const struct GC_finalizer_closure *fclos)
      87             : #else
      88             :   GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb,
      89             :                                 const struct GC_finalizer_closure *fclos)
      90             : #endif
      91             : {
      92             :     ptr_t op;
      93             :     ptr_t *opp;
      94             :     word lg;
      95             :     DCL_LOCK_STATE;
      96             : 
      97           0 :     lb += sizeof(word);
      98             :     GC_ASSERT(done_init);
      99           0 :     if (SMALL_OBJ(lb)) {
     100             :         GC_DBG_COLLECT_AT_MALLOC(lb);
     101           0 :         lg = GC_size_map[lb];
     102           0 :         opp = &GC_finalized_objfreelist[lg];
     103           0 :         LOCK();
     104           0 :         op = *opp;
     105           0 :         if (EXPECT(0 == op, FALSE)) {
     106           0 :             UNLOCK();
     107           0 :             op = GC_generic_malloc((word)lb, GC_finalized_kind);
     108           0 :             if (NULL == op)
     109           0 :                 return NULL;
     110             :             /* GC_generic_malloc has extended the size map for us.      */
     111           0 :             lg = GC_size_map[lb];
     112             :         } else {
     113           0 :             *opp = obj_link(op);
     114           0 :             obj_link(op) = 0;
     115           0 :             GC_bytes_allocd += GRANULES_TO_BYTES(lg);
     116           0 :             UNLOCK();
     117             :         }
     118             :         GC_ASSERT(lg > 0);
     119             :     } else {
     120           0 :         op = GC_generic_malloc(lb, GC_finalized_kind);
     121           0 :         if (NULL == op)
     122           0 :             return NULL;
     123             :         GC_ASSERT(GC_size(op) >= lb);
     124             :     }
     125           0 :     *(word *)op = (word)fclos | 1;
     126           0 :     return GC_clear_stack((word *)op + 1);
     127             : }
     128             : 
     129             : #ifdef THREAD_LOCAL_ALLOC
     130           0 :   GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t client_lb,
     131             :                                 const struct GC_finalizer_closure *fclos)
     132             :   {
     133           0 :     size_t lb = client_lb + sizeof(word);
     134           0 :     size_t lg = ROUNDED_UP_GRANULES(lb);
     135             :     GC_tlfs tsd;
     136             :     void *result;
     137             :     void **tiny_fl, **my_fl, *my_entry;
     138             :     void *next;
     139             : 
     140           0 :     if (EXPECT(lg >= GC_TINY_FREELISTS, FALSE))
     141           0 :         return GC_core_finalized_malloc(client_lb, fclos);
     142             : 
     143           0 :     tsd = GC_getspecific(GC_thread_key);
     144           0 :     tiny_fl = tsd->finalized_freelists;
     145           0 :     my_fl = tiny_fl + lg;
     146           0 :     my_entry = *my_fl;
     147           0 :     while (EXPECT((word)my_entry
     148             :                   <= DIRECT_GRANULES + GC_TINY_FREELISTS + 1, FALSE)) {
     149           0 :         if ((word)my_entry - 1 < DIRECT_GRANULES) {
     150           0 :             *my_fl = (ptr_t)my_entry + lg + 1;
     151           0 :             return GC_core_finalized_malloc(client_lb, fclos);
     152             :         } else {
     153           0 :             GC_generic_malloc_many(GC_RAW_BYTES_FROM_INDEX(lg),
     154             :                                    GC_finalized_kind, my_fl);
     155           0 :             my_entry = *my_fl;
     156           0 :             if (my_entry == 0) {
     157           0 :                 return (*GC_get_oom_fn())(lb);
     158             :             }
     159             :         }
     160             :     }
     161             : 
     162           0 :     next = obj_link(my_entry);
     163           0 :     result = (void *)my_entry;
     164           0 :     *my_fl = next;
     165           0 :     obj_link(result) = 0;
     166           0 :     *(word *)result = (word)fclos | 1;
     167           0 :     PREFETCH_FOR_WRITE(next);
     168           0 :     return (word *)result + 1;
     169             :   }
     170             : #endif /* THREAD_LOCAL_ALLOC */
     171             : 
     172             : #endif /* ENABLE_DISCLAIM */

Generated by: LCOV version 1.11