~ubuntu-branches/ubuntu/precise/ghc/precise

« back to all changes in this revision

Viewing changes to libraries/integer-gmp/cbits/alloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Joachim Breitner
  • Date: 2011-01-17 12:49:24 UTC
  • Revision ID: james.westby@ubuntu.com-20110117124924-do1pym1jlf5o636m
Tags: upstream-7.0.1
ImportĀ upstreamĀ versionĀ 7.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -----------------------------------------------------------------------------
 
2
 *
 
3
 * (c) The GHC Team, 1998-2008
 
4
 *
 
5
 * ---------------------------------------------------------------------------*/
 
6
 
 
7
/* TODO: do we need PosixSource.h ? it lives in rts/ not public includes/ */
 
8
/* #include "PosixSource.h" */
 
9
#include "Rts.h"
 
10
 
 
11
#include "gmp.h"
 
12
 
 
13
void * stgAllocForGMP   (size_t size_in_bytes);
 
14
void * stgReallocForGMP (void *ptr, size_t old_size, size_t new_size);
 
15
void   stgDeallocForGMP (void *ptr STG_UNUSED, size_t size STG_UNUSED);
 
16
 
 
17
static void initAllocForGMP( void ) __attribute__((constructor));
 
18
 
 
19
/* -----------------------------------------------------------------------------
 
20
   Tell GMP to use our custom heap allocation functions.
 
21
 
 
22
   Our allocation strategy is to use GHC heap allocations rather than malloc
 
23
   and co. The heap objects we use are ByteArray#s which of course have their
 
24
   usual header word or two. But gmp doesn't know about ghc heap objects and
 
25
   header words. So our allocator has to make a ByteArray# and return a pointer
 
26
   to its interior! When the gmp function returns we recieve that interior
 
27
   pointer. Then we look back a couple words to get the propper ByteArray#
 
28
   pointer (which then gets returned as a ByteArray# and thus get tracked
 
29
   properly by the GC).
 
30
 
 
31
   WARNING!! WARNING!! WARNING!!
 
32
 
 
33
     It is absolutely vital that this initialisation function be called before
 
34
     any of the gmp functions are called. We'd still be looking back a couple
 
35
     words for the ByteArray# header, but if we were accidentally using malloc
 
36
     then it'd all go wrong because of course there would be no ByteArray#
 
37
     header, just malloc's own internal book keeping info. To make things worse
 
38
     we would not notice immediately, it'd only be when the GC comes round to
 
39
     inspect things... BANG!
 
40
 
 
41
     > Program received signal SIGSEGV, Segmentation fault.
 
42
     > [Switching to Thread 0x7f5a9ebc76f0 (LWP 17838)]
 
43
     > evacuate1 (p=0x7f5a99acd2e0) at rts/sm/Evac.c:375
 
44
     > 375       switch (info->type) {
 
45
 
 
46
   -------------------------------------------------------------------------- */
 
47
 
 
48
static void initAllocForGMP( void )
 
49
{
 
50
  mp_set_memory_functions(stgAllocForGMP, stgReallocForGMP, stgDeallocForGMP);
 
51
}
 
52
 
 
53
 
 
54
/* -----------------------------------------------------------------------------
 
55
   Allocation functions for GMP.
 
56
 
 
57
   These all use the allocate() interface - we can't have any garbage
 
58
   collection going on during a gmp operation, so we use allocate()
 
59
   which always succeeds.  The gmp operations which might need to
 
60
   allocate will ask the storage manager (via doYouWantToGC()) whether
 
61
   a garbage collection is required, in case we get into a loop doing
 
62
   only allocate() style allocation.
 
63
   -------------------------------------------------------------------------- */
 
64
 
 
65
void *
 
66
stgAllocForGMP (size_t size_in_bytes)
 
67
{
 
68
  StgArrWords* arr;
 
69
  nat data_size_in_words, total_size_in_words;
 
70
 
 
71
  /* round up to a whole number of words */
 
72
  data_size_in_words  = ROUNDUP_BYTES_TO_WDS(size_in_bytes);
 
73
  total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
 
74
 
 
75
  /* allocate and fill it in. */
 
76
  arr = (StgArrWords *)allocate(rts_unsafeGetMyCapability(), total_size_in_words);
 
77
  SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, size_in_bytes);
 
78
 
 
79
  /* and return a ptr to the goods inside the array */
 
80
  return arr->payload;
 
81
}
 
82
 
 
83
void *
 
84
stgReallocForGMP (void *ptr, size_t old_size, size_t new_size)
 
85
{
 
86
    size_t min_size;
 
87
    void *new_stuff_ptr = stgAllocForGMP(new_size);
 
88
    nat i = 0;
 
89
    char *p = (char *) ptr;
 
90
    char *q = (char *) new_stuff_ptr;
 
91
 
 
92
    min_size = old_size < new_size ? old_size : new_size;
 
93
    /* TODO: use memcpy */
 
94
    for (; i < min_size; i++, p++, q++) {
 
95
        *q = *p;
 
96
    }
 
97
 
 
98
    return(new_stuff_ptr);
 
99
}
 
100
 
 
101
void
 
102
stgDeallocForGMP (void *ptr STG_UNUSED, size_t size STG_UNUSED)
 
103
{
 
104
    /* easy for us: the garbage collector does the dealloc'n */
 
105
}