1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 1994-2006 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s): Joachim Schimpf, ECRC.
20 *
21 * END LICENSE BLOCK */
22
23/*---------------------------------------------------------------------
24 * IDENTIFICATION	private_mem.c
25 *
26 * VERSION		$Id: private_mem.c,v 1.2 2007/07/03 00:10:25 jschimpf Exp $
27 *
28 * AUTHOR		Joachim Schimpf
29 *
30 * CONTENTS		- Private memory allocation
31 *---------------------------------------------------------------------*/
32
33#include	"config.h"
34#ifdef HAVE_UNISTD_H
35#include	<unistd.h>
36#endif
37#ifdef HAVE_WINDOWS_H
38#include	"windows.h"
39#endif
40
41#ifdef HAVE_MMAP
42#define USE_MMAP
43#endif
44
45#ifdef USE_MMAP
46
47#include <sys/mman.h>
48#include <fcntl.h>	/* for O_RDWR */
49
50#ifndef MAP_FAILED
51#define MAP_FAILED ((void *) -1)
52#endif
53
54#ifdef MAP_ANONYMOUS
55#define HAVE_MAP_ANONYMOUS
56#else
57#ifdef MAP_ANON
58#define MAP_ANONYMOUS MAP_ANON
59#define HAVE_MAP_ANONYMOUS
60#else
61#define MAP_ANONYMOUS 0
62#endif
63#endif
64
65#else
66
67#ifdef SBRK_UNDEF
68extern char *sbrk();
69#endif
70
71#endif
72
73
74#include	"memman.h"
75
76
77struct prmem {
78	/* first word reserved to be compatible with shared memory's
79	 * application_header
80	 */
81	generic_ptr first_word_in_heap;
82	struct page_admin pages;
83	struct heap heap;
84};
85
86struct heap_descriptor private_heap;
87
88
89/*---------------------------------------------------------------------
90 * Primitive allocation function for private memory
91 *---------------------------------------------------------------------*/
92
93/*ARGSUSED*/
94static generic_ptr
95_private_sbrk(word size, int align, struct heap_descriptor *hd)
96{
97#ifdef HAVE_WINDOWS_H
98    generic_ptr address = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE);
99    return address ? address : (generic_ptr) -1;
100#else
101#ifdef USE_MMAP
102    generic_ptr address = mmap((void*) 0, size,
103	    PROT_READ|PROT_WRITE,
104	    MAP_ANONYMOUS|MAP_PRIVATE,
105	    hd->map_fd, (off_t) 0);
106    return address == MAP_FAILED ? (generic_ptr) -1 : address;
107#else
108    register word difference = (word) sbrk(0) % align;
109    if (difference)
110    {
111#ifdef DEBUG_HEAP
112    	(void) write(2, "WARNING: misaligned brk\n", 24);
113#endif
114	(void) sbrk(align - difference);
115    }
116    return (generic_ptr) sbrk(size);
117#endif
118#endif
119}
120
121static int
122_private_release(generic_ptr address, word size, struct heap_descriptor *hd)
123{
124#ifdef HAVE_WINDOWS_H
125    return VirtualFree(address, 0, MEM_RELEASE);
126#else
127#ifdef USE_MMAP
128    return !munmap(address, size);
129#else
130    return 1;
131#endif
132#endif
133}
134
135char *
136private_mem_init_desc(
137	void (*panic_fct)(const char*, const char*),
138	struct heap_descriptor *hd)
139{
140    struct prmem *private_memory;
141    /*
142     * Set up the private heap
143     */
144#ifdef USE_MMAP
145#ifdef HAVE_MAP_ANONYMOUS
146    hd->map_fd = -1;
147#else
148    hd->map_fd = open("/dev/zero", O_RDWR);
149#endif
150#endif
151    private_memory = (struct prmem *)
152	_private_sbrk(sizeof(struct prmem), 1, hd);
153    if (private_memory == (struct prmem *) -1)
154    	return (char *) -1;
155
156    hd->shared_header = 0;
157    hd->pages = &private_memory->pages;
158    hd->heap = &private_memory->heap;
159    hd->panic = panic_fct;
160    hd->more = _private_sbrk;
161    hd->less = _private_release;
162    pagemanager_init(hd);
163    alloc_init(hd);
164    return (char *) private_memory;
165}
166
167void
168private_mem_init(void (*panic_fct)(const char*, const char*))
169{
170    Disable_Int();
171    (void) private_mem_init_desc(panic_fct, &private_heap);
172    Enable_Int();
173}
174
175void
176private_mem_release_desc(struct heap_descriptor *hd)
177{
178    struct prmem dummy;
179    char *prmem_struct_addr;
180    pagemanager_fini(hd);
181    /* sorry, hack to find lost address of the above allocated structure */
182    prmem_struct_addr = (char*)hd->pages - ((char*)&dummy.pages - (char*)&dummy);
183    _private_release(prmem_struct_addr, sizeof(struct prmem), NULL);
184}
185
186void
187private_mem_release()
188{
189    Disable_Int();
190    (void) private_mem_release_desc(&private_heap);
191    Enable_Int();
192}
193
194
195/*---------------------------------------------------------------------
196 * Private heap interface
197 *---------------------------------------------------------------------*/
198
199/*
200 * Header-less allocation
201 */
202
203generic_ptr
204hp_alloc_size(word bytes_needed)
205{
206    return alloc_size(&private_heap, bytes_needed);
207}
208
209void
210hp_free_size(generic_ptr ptr, word size)
211{
212    free_size(&private_heap, ptr, size);
213}
214
215generic_ptr
216hp_realloc_size(generic_ptr ptr, word oldsize, word newsize)
217{
218    return realloc_size(&private_heap, ptr, oldsize, newsize);
219}
220
221
222/*---------------------------------------------------------------------
223 * Allocate memory that remembers its own size
224 * We need a double header for alignment.
225 * It gives us also space for a magic number.
226 *---------------------------------------------------------------------*/
227
228generic_ptr
229hp_alloc(word size)
230{
231    return h_alloc(&private_heap, size);
232}
233
234void
235hp_free(generic_ptr ptr)
236{
237    h_free(&private_heap, ptr);
238}
239
240generic_ptr
241hp_resize(generic_ptr ptr, word newsize)
242{
243    return h_realloc(&private_heap, ptr, newsize);
244}
245
246
247/*---------------------------------------------------------------------
248 * Debugging and statistics
249 *---------------------------------------------------------------------*/
250
251int
252hp_statistics(int what)
253{
254    return alloc_statistics(&private_heap, what);
255}
256
257