1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: alloc.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #undef OSL_DEBUG_LEVEL
33 #define OSL_DEBUG_LEVEL 0
36 #include <sal/types.h>
37 #include <osl/diagnose.h>
38 #include <rtl/alloc.h>
40 #ifndef INCLUDED_STDDEF_H
42 #define INCLUDED_STDDEF_H
45 #ifndef INCLUDED_STDLIB_H
47 #define INCLUDED_STDLIB_H
50 #ifndef INCLUDED_STRING_H
52 #define INCLUDED_STRING_H
55 #ifndef FORCE_SYSALLOC
57 /*===========================================================================
59 * rtl_memory (UNX) internals.
61 *=========================================================================*/
69 typedef pthread_mutex_t mutex_type
;
71 #define RTL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
72 #define RTL_MUTEX_ACQUIRE(a) pthread_mutex_lock((a))
73 #define RTL_MUTEX_RELEASE(a) pthread_mutex_unlock((a))
75 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
76 static sal_Size
__rtl_memory_vmpagesize (void)
79 return (sal_Size
)(getpagesize());
81 #elif defined(IRIX) || defined(LINUX) || defined(SOLARIS)
82 static sal_Size
__rtl_memory_vmpagesize (void)
85 return (sal_Size
)(sysconf(_SC_PAGESIZE
));
88 static sal_Size
__rtl_memory_vmpagesize (void)
91 return (sal_Size
)(0x2000);
93 #endif /* FREEBSD || NETBSD || MACOSX || IRIX || LINUX || SOLARIS */
96 #define PROT_HEAP (PROT_READ | PROT_WRITE | PROT_EXEC)
99 /* #95880# building on Solaris 8 provides MAP_ANON, but it
100 is not available on Solaris 7 */
101 #if defined (SOLARIS)
108 static void* __rtl_memory_vmalloc (sal_Size n
)
111 int fd
= open("/dev/zero", O_RDWR
);
114 void * p
= mmap(NULL
, n
, PROT_HEAP
, MAP_PRIVATE
, fd
, 0);
116 return ((p
== MAP_FAILED
) ? NULL
: p
);
121 static void* __rtl_memory_vmalloc (sal_Size n
)
124 void * p
= mmap(NULL
, n
, PROT_HEAP
, MAP_PRIVATE
| MAP_ANON
, -1, 0);
125 return ((p
== MAP_FAILED
) ? NULL
: p
);
127 #endif /* MAP_ANON */
129 #define RTL_MEMORY_ALLOC(n) __rtl_memory_vmalloc((sal_Size)(n))
130 #define RTL_MEMORY_FREE(p, n) munmap((void*)(p), (sal_Size)(n))
134 /*===========================================================================
136 * rtl_memory (W32) internals.
138 *=========================================================================*/
141 #define WIN32_LEAN_AND_MEAN
143 #pragma warning(push,1) /* disable warnings within system headers */
148 typedef CRITICAL_SECTION mutex_type
;
150 /* Static initializer (struct declared in WINNT.H). */
151 #define RTL_MUTEX_INITIALIZER { NULL, -1, 0, NULL, NULL, 0 }
154 * __rtl_mutex_init (dynamic initialization).
156 * Static initialization (with DebugInfo == NULL)
157 * leads to Access Violation upon first contention.
159 static void __rtl_mutex_init (LPCRITICAL_SECTION lpCriticalSection
)
161 static LONG g_spinlock
= 0;
163 while (InterlockedExchange (&g_spinlock
, 1) == 1)
165 /* Already locked, spin */
168 if (!(lpCriticalSection
->DebugInfo
))
170 /* Dynamic initialization */
171 InitializeCriticalSection (lpCriticalSection
);
173 InterlockedExchange (&g_spinlock
, 0);
176 #define RTL_MUTEX_INIT(a) __rtl_mutex_init((LPCRITICAL_SECTION)(a))
177 #define RTL_MUTEX_ACQUIRE(a) EnterCriticalSection((a))
178 #define RTL_MUTEX_RELEASE(a) LeaveCriticalSection((a))
180 static sal_Size
__rtl_memory_vmpagesize (void)
183 GetSystemInfo (&info
);
184 return ((sal_Size
)(info
.dwPageSize
));
187 #define RTL_MEMORY_ALLOC(n) \
188 (void*)(VirtualAlloc (NULL, (SIZE_T)(n), MEM_COMMIT, PAGE_READWRITE))
190 #define RTL_MEMORY_FREE(p, n) \
191 (void)(VirtualFree ((LPVOID)(p), (SIZE_T)(0), MEM_RELEASE))
195 /*===========================================================================
197 * rtl_memory (OS2) internals.
199 *=========================================================================*/
205 typedef HMTX mutex_type
;
207 /* Static initializer */
208 #define RTL_MUTEX_INITIALIZER -1
211 * __rtl_mutex_init (dynamic initialization).
213 * Static initialization (with DebugInfo == NULL)
214 * leads to Access Violation upon first contention.
216 static void __rtl_mutex_init (mutex_type
* mutex
)
220 rc
= DosCreateMutexSem(NULL
,mutex
,0,0);
224 static int __rtl_mutex_destroy (mutex_type
* mutex
)
230 rc
= DosCloseMutexSem(*mutex
);
231 if (rc
== 301) DosReleaseMutexSem(*mutex
);
236 /* Return the completion status: */
241 static int __rtl_mutex_acquire(mutex_type
* mutex
)
247 // initialize static semaphores created with PTHREAD_MUTEX_INITIALIZER state.
249 __rtl_mutex_init( mutex
);
251 rc
= DosRequestMutexSem(*mutex
,SEM_INDEFINITE_WAIT
);
255 /* Return the completion status: */
259 static int __rtl_mutex_release(mutex_type
* mutex
)
266 // initialize static semaphores created with PTHREAD_MUTEX_INITIALIZER state.
268 __rtl_mutex_init( mutex
);
270 rc
= DosReleaseMutexSem(*mutex
);
272 /* Return the completion status: */
276 #define RTL_MUTEX_INIT(a) __rtl_mutex_init((mutex_type*)(a))
277 #define RTL_MUTEX_ACQUIRE(a) __rtl_mutex_acquire((mutex_type*)(a))
278 #define RTL_MUTEX_RELEASE(a) __rtl_mutex_release((mutex_type*)(a))
280 static sal_Size
__rtl_memory_vmpagesize (void)
282 return (sal_Size
)(getpagesize());
285 #define RTL_MEMORY_ALLOC(n) (void*)(malloc(n))
287 #define RTL_MEMORY_FREE(p, n) (void)(free(p))
291 /*===========================================================================
293 * Determine allocation mode (debug/release) by examining environment
294 * variable "OOO_FORCE_SYSALLOC".
296 *=========================================================================*/
298 #include <stdlib.h> /* getenv */
299 #include <stdio.h> /* stderr */
302 enum { AMode_CUSTOM
, AMode_SYSTEM
, AMode_UNSET
}
305 static AllocMode alloc_mode
= AMode_UNSET
;
307 static void determine_alloc_mode ( void )
309 /* This shouldn't happen, but still ... */
310 if (alloc_mode
!= AMode_UNSET
)
313 if (getenv("OOO_FORCE_SYSALLOC") != NULL
) {
314 alloc_mode
= AMode_SYSTEM
;
315 fprintf(stderr
, "OOo: Using system memory allocator.\n");
316 fprintf(stderr
, "OOo: This is for debugging only. To disable,\n");
317 fprintf(stderr
, "OOo: unset the environment variable"
318 " OOO_FORCE_SYSALLOC.\n");
320 alloc_mode
= AMode_CUSTOM
;
324 /*===========================================================================
326 * rtl_memory (global) internals.
328 *=========================================================================*/
331 #define __N__ ((__L__) + (__P__))
332 #define __M__ 0x10000
334 static const sal_Size __T__
= (__M__
) * 2 / 3;
336 typedef struct __rtl_memory_desc_st memory_type
;
337 struct __rtl_memory_desc_st
341 memory_type
*m_flink
;
342 memory_type
*m_blink
;
345 static const int __C__
= 2 * sizeof(sal_Size
);
346 static const int __Q__
= 2 * sizeof(memory_type
*);
348 typedef struct __rtl_memory_stat_st memory_stat
;
349 struct __rtl_memory_stat_st
351 sal_uInt64 m_dequeue
;
352 sal_uInt64 m_enqueue
;
355 sal_uInt64 m_deqsize
;
356 sal_uInt64 m_enqsize
;
360 #define RTL_MEMORY_ALIGN(n, m) (((n) + ((m) - 1)) & ~((m) - 1))
361 #define RTL_MEMORY_SIZEOF(a) RTL_MEMORY_ALIGN(sizeof(a), sizeof(memory_type))
363 struct __rtl_memory_global_st
370 char m_data
[RTL_MEMORY_SIZEOF(mutex_type
)];
373 memory_type m_alloc_head
;
374 memory_type m_spare_head
;
375 memory_type m_queue_head
[__N__
];
377 #if OSL_DEBUG_LEVEL > 0
378 memory_stat m_queue_stat
[__N__
];
379 #endif /* OSL_DEBUG_LEVEL */
382 static struct __rtl_memory_global_st g_memory
=
384 0, 0, { RTL_MUTEX_INITIALIZER
},
385 { 0, 0, NULL
, NULL
}, { 0, 0, NULL
, NULL
}, { { 0, 0, NULL
, NULL
} },
386 #if OSL_DEBUG_LEVEL > 0
387 { { 0, 0, 0, 0, 0, 0 } }
388 #endif /* OSL_DEBUG_LEVEL */
391 void SAL_CALL
___rtl_memory_init (void);
392 void SAL_CALL
___rtl_memory_fini (void);
394 #define RTL_MEMORY_ENTER() \
396 if (!(g_memory.m_align)) ___rtl_memory_init(); \
397 RTL_MUTEX_ACQUIRE(&(g_memory.m_mutex.m_lock)); \
400 #define RTL_MEMORY_LEAVE() \
402 RTL_MUTEX_RELEASE(&(g_memory.m_mutex.m_lock)); \
405 /*===========================================================================
407 * rtl_memory (queue) internals.
409 *=========================================================================*/
410 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
411 static sal_Size
queue (sal_Size n
)
413 /* k = n div __C__ */
414 register sal_Size k
= n
/ __C__
, m
= __L__
;
416 OSL_PRECOND((__L__
== 32),
417 "__rtl_memory_queue(): internal logic error");
420 /* k = k div __L__ = k div 32 */
422 while ((k
>>= 1) > 0) m
++;
426 OSL_POSTCOND((0 < k
) && (k
< __N__
),
427 "__rtl_memory_queue(): "
428 "internal error: index out of bounds");
432 #define queue(k, n) \
434 (k) = ((n) / __C__); \
437 register sal_Size m = __L__; \
439 while (((k) >>= 1) > 0) m++; \
443 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
445 #define queue_start(entry) \
447 (entry)->m_flink = (entry); \
448 (entry)->m_blink = (entry); \
451 #define queue_remove(entry) \
453 (entry)->m_blink->m_flink = (entry)->m_flink; \
454 (entry)->m_flink->m_blink = (entry)->m_blink; \
455 queue_start(entry); \
458 #define queue_insert_head(head, entry) \
460 (entry)->m_blink = (head); \
461 (entry)->m_flink = (head)->m_flink; \
462 (head)->m_flink = (entry); \
463 (entry)->m_flink->m_blink = (entry); \
466 #define queue_insert_tail(head, entry) \
468 (entry)->m_flink = (head); \
469 (entry)->m_blink = (head)->m_blink; \
470 (head)->m_blink = (entry); \
471 (entry)->m_blink->m_flink = (entry); \
474 /*===========================================================================
476 * rtl_memory (debug) internals.
478 *=========================================================================*/
479 #if OSL_DEBUG_LEVEL > 0
481 #define __dbg_memory_succ(entry, length) \
482 (memory_type*)((char*)((entry)) + ((length) & ~0x1))
484 #define __dbg_memory_pred(entry, offset) \
485 (memory_type*)((char*)((entry)) - ((offset) & ~0x1))
487 #define __dbg_memory_ensure(entry) (!((sal_Size)(entry) & 0x7))
490 * __dbg_memory_dequeue.
492 static void __dbg_memory_dequeue (sal_Size n
)
494 register sal_Size k
= queue(n
);
496 g_memory
.m_queue_stat
[k
].m_dequeue
+= 1;
497 g_memory
.m_queue_stat
[k
].m_delta_q
+= 1;
499 g_memory
.m_queue_stat
[k
].m_deqsize
+= n
;
500 g_memory
.m_queue_stat
[k
].m_delta_n
+= n
;
504 * __dbg_memory_enqueue.
506 static void __dbg_memory_enqueue (sal_Size n
)
508 register sal_Size k
= queue(n
);
510 g_memory
.m_queue_stat
[k
].m_enqueue
+= 1;
511 g_memory
.m_queue_stat
[k
].m_delta_q
-= 1;
513 g_memory
.m_queue_stat
[k
].m_enqsize
+= n
;
514 g_memory
.m_queue_stat
[k
].m_delta_n
-= n
;
518 * __dbg_memory_insert.
520 static void __dbg_memory_insert (memory_type
**ppMemory
)
522 register memory_type
* succ
;
523 succ
= __dbg_memory_succ (*ppMemory
, sizeof(memory_type
));
525 succ
->m_length
= (*ppMemory
)->m_length
- sizeof(memory_type
);
526 succ
->m_offset
= (*ppMemory
)->m_offset
;
528 queue_insert_tail (&(g_memory
.m_alloc_head
), (*ppMemory
));
533 * __dbg_memory_remove.
535 static void __dbg_memory_remove (memory_type
**ppMemory
)
537 (*ppMemory
) = __dbg_memory_pred (*ppMemory
, sizeof(memory_type
));
538 queue_remove (*ppMemory
);
542 * __dbg_memory_verify_chain.
544 static int __dbg_memory_verify_chain (memory_type
* x
)
546 if (!__dbg_memory_ensure(x
))
548 OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
551 if (!__dbg_memory_ensure(x
->m_length
& ~0x1))
553 OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
556 if (!__dbg_memory_ensure(x
->m_offset
& ~0x1))
558 OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
561 if (!(x
->m_length
& ~0x1))
563 OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
570 * __dbg_memory_verify_queue.
572 static int __dbg_memory_verify_queue (memory_type
* x
)
574 if (!__dbg_memory_ensure(x
))
576 OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
579 if (!__dbg_memory_ensure(x
->m_flink
))
581 OSL_ENSURE(0, "__rtl_memory_verify(): free memory corruption");
584 if (!__dbg_memory_ensure(x
->m_blink
))
586 OSL_ENSURE(0, "__rtl_memory_verify(): free memory corruption");
589 if ((x
== x
->m_flink
) || (x
== x
->m_blink
))
591 OSL_ENSURE(0, "__rtl_memory_verify(): internal logic error");
598 * __dbg_memory_verify_alloc.
600 static int __dbg_memory_verify_alloc (memory_type
* x
)
602 register memory_type
*head
, *entry
;
603 head
= entry
= &(g_memory
.m_alloc_head
);
605 if (!__dbg_memory_ensure(x
))
607 OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
610 while (!((entry
= entry
->m_flink
) == head
))
612 if ((entry
< x
) && (x
< __dbg_memory_succ(entry
, entry
->m_length
)))
614 head
= entry
= __dbg_memory_succ(entry
, sizeof(memory_type
));
615 while (!((x
== entry
) || (entry
->m_offset
& 0x1)))
617 /* no match, not last */
618 if (!__dbg_memory_verify_chain (entry
))
620 entry
= __dbg_memory_succ(entry
, entry
->m_length
);
624 if (!__dbg_memory_verify_chain (entry
))
631 OSL_ENSURE(0, "__rtl_memory_verify(): memory not allocated.");
638 * __dbg_memory_verify.
640 static int __dbg_memory_verify (memory_type
* x
, int debug
)
642 /* dispatch upon 'debug' level */
645 /* verify allocation */
646 if (!__dbg_memory_verify_alloc (x
))
651 /* verify 'chain' fields */
652 if (!__dbg_memory_verify_chain (x
))
656 /* verify 'used' bit */
657 if (!(x
->m_length
& 0x1))
659 OSL_ENSURE(0, "__rtl_memory_verify(): memory not used.");
665 #if OSL_DEBUG_LEVEL > 1
667 * __dbg_memory_usage_update.
669 static sal_Size
__dbg_memory_usage_update (memory_stat
* stat
, sal_Size length
)
671 register sal_Size n
= (length
& ~0x1), k
= queue(n
);
673 stat
[k
].m_dequeue
+= 1;
674 stat
[k
].m_deqsize
+= n
;
679 stat
[k
].m_enqueue
+= 1;
680 stat
[k
].m_enqsize
+= n
;
686 stat
[k
].m_delta_q
+= 1;
687 stat
[k
].m_delta_n
+= n
;
693 * __dbg_memory_usage.
695 static void __dbg_memory_usage (memory_stat
* total
)
697 register memory_type
*head
, *entry
, *memory
;
698 memory_stat stat
[__N__
];
700 memset (stat
, 0, __N__
* sizeof(memory_stat
));
702 head
= entry
= &(g_memory
.m_alloc_head
);
703 while (!((entry
= entry
->m_flink
) == head
))
705 register sal_Size k
= 0, n
= entry
->m_length
- sizeof(memory_type
);
707 memory
= __dbg_memory_succ(entry
, sizeof(memory_type
));
708 while (!(memory
->m_offset
& 0x1))
711 k
+= __dbg_memory_usage_update (stat
, memory
->m_length
);
712 memory
= __dbg_memory_succ(memory
, memory
->m_length
);
715 k
+= __dbg_memory_usage_update (stat
, memory
->m_length
);
716 OSL_TRACE("%x %10d %10d", (sal_Size
)(entry
), n
, k
);
723 memset (total
, 0, sizeof(memory_stat
));
724 for (i
= 0; i
< __N__
; i
++)
726 total
->m_dequeue
+= stat
[i
].m_dequeue
;
727 total
->m_enqueue
+= stat
[i
].m_enqueue
;
728 total
->m_delta_q
+= stat
[i
].m_delta_q
;
730 total
->m_deqsize
+= stat
[i
].m_deqsize
;
731 total
->m_enqsize
+= stat
[i
].m_enqsize
;
732 total
->m_delta_n
+= stat
[i
].m_delta_n
;
736 #endif /* OSL_DEBUG_LEVEL */
738 #endif /* OSL_DEBUG_LEVEL */
739 #if OSL_DEBUG_LEVEL > 0
741 #define DBG_MEMORY_DEQUEUE(n) __dbg_memory_dequeue((sal_Size)(n) & ~0x1)
742 #define DBG_MEMORY_ENQUEUE(n) __dbg_memory_enqueue((sal_Size)(n) & ~0x1)
744 #define DBG_MEMORY_DEQFILL(entry, offset, length) \
745 memset(((char*)(entry) + (offset)), 0x77777777, (length))
746 #define DBG_MEMORY_ENQFILL(entry, offset, length) \
747 memset(((char*)(entry) + (offset)), 0x33333333, (length))
749 #define DBG_MEMORY_INSERT(entry) __dbg_memory_insert((entry))
750 #define DBG_MEMORY_REMOVE(entry) __dbg_memory_remove((entry))
752 #if OSL_DEBUG_LEVEL > 1
753 #define DBG_MEMORY_VERIFY(entry) __dbg_memory_verify((entry), 1)
754 #else /* OSL_DEBUG_LEVEL > 0 */
755 #define DBG_MEMORY_VERIFY(entry) __dbg_memory_verify((entry), 0)
756 #endif /* OSL_DEBUG_LEVEL */
758 #define DBG_MEMORY_VERIFY_CHAIN(entry) __dbg_memory_verify_chain((entry))
759 #define DBG_MEMORY_VERIFY_QUEUE(entry) __dbg_memory_verify_queue((entry))
763 #define DBG_MEMORY_DEQUEUE(n)
764 #define DBG_MEMORY_ENQUEUE(n)
766 #define DBG_MEMORY_DEQFILL(entry, offset, length)
767 #define DBG_MEMORY_ENQFILL(entry, offset, length)
769 #define DBG_MEMORY_INSERT(entry)
770 #define DBG_MEMORY_REMOVE(entry)
772 #define DBG_MEMORY_VERIFY(entry)
773 #define DBG_MEMORY_VERIFY_CHAIN(entry)
774 #define DBG_MEMORY_VERIFY_QUEUE(entry)
776 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
778 /*===========================================================================
780 * rtl_memory (manager) internals.
782 *=========================================================================*/
783 #define queue_cast(entry, offset) \
784 ((memory_type*)((char*)(entry) + (ptrdiff_t)(offset)))
786 #define __rtl_memory_used(entry) ((entry)->m_length & 0x1)
787 #define __rtl_memory_last(entry) ((entry)->m_offset & 0x1)
788 #define __rtl_memory_offset(entry) \
789 ((ptrdiff_t)((entry)->m_offset & ~0x1))
792 * ___rtl_memory_init.
794 void SAL_CALL
___rtl_memory_init (void)
796 #if defined(RTL_MUTEX_INIT)
797 RTL_MUTEX_INIT (&(g_memory
.m_mutex
.m_lock
));
798 #endif /* RTL_MUTEX_INIT */
800 RTL_MUTEX_ACQUIRE(&(g_memory
.m_mutex
.m_lock
));
801 if (!(g_memory
.m_align
))
806 queue_start (&(g_memory
.m_alloc_head
));
807 queue_start (&(g_memory
.m_spare_head
));
809 for (i
= 0; i
< __N__
; i
++)
810 queue_start (&(g_memory
.m_queue_head
[i
]));
811 for (i
= 1; i
<= __L__
; i
++)
812 g_memory
.m_queue_head
[i
].m_length
= i
* __C__
;
813 for (i
= __L__
+ 1; i
< __N__
; i
++)
814 g_memory
.m_queue_head
[i
].m_length
=
815 2 * g_memory
.m_queue_head
[i
- 1].m_length
;
817 pagesize
= __rtl_memory_vmpagesize();
818 g_memory
.m_align
= RTL_MEMORY_ALIGN(__M__
, pagesize
);
820 RTL_MUTEX_RELEASE(&(g_memory
.m_mutex
.m_lock
));
824 * ___rtl_memory_fini.
826 void SAL_CALL
___rtl_memory_fini (void)
828 #if OSL_DEBUG_LEVEL > 1
832 __dbg_memory_usage (&total
);
833 if (total
.m_delta_n
> 0)
835 OSL_TRACE("___rtl_memory_fini(): "
836 "Leak: %10d (Alloc: %10d, Free: %10d)",
838 (sal_uInt32
)(total
.m_deqsize
& 0xffffffff),
839 (sal_uInt32
)(total
.m_enqsize
& 0xffffffff));
842 #endif /* OSL_DEBUG_LEVEL */
846 * __rtl_memory_merge.
848 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
849 static void __rtl_memory_merge (memory_type
* prev
, memory_type
* next
)
852 prev
->m_length
+= next
->m_length
;
853 if (!__rtl_memory_last(next
))
855 /* not last, adjust offset */
856 register memory_type
* succ
= queue_cast(prev
, prev
->m_length
);
857 DBG_MEMORY_VERIFY_CHAIN (succ
);
858 succ
->m_offset
= prev
->m_length
| __rtl_memory_last(succ
);
861 /* propagate 'last' bit */
862 prev
->m_offset
|= __rtl_memory_last(next
);
865 #define __rtl_memory_merge(prev, next) \
867 (prev)->m_length += (next)->m_length; \
868 if (!__rtl_memory_last((next))) \
870 register memory_type * succ = queue_cast((prev), (prev)->m_length); \
871 succ->m_offset = (prev)->m_length | __rtl_memory_last(succ); \
873 (prev)->m_offset |= __rtl_memory_last((next)); \
875 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
878 * __rtl_memory_split.
880 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
881 static void __rtl_memory_split (memory_type
* prev
, memory_type
* next
)
884 prev
->m_length
-= next
->m_length
;
885 if (!__rtl_memory_last(prev
))
887 /* not last, adjust offset */
888 register memory_type
* succ
= queue_cast(next
, next
->m_length
);
889 DBG_MEMORY_VERIFY_CHAIN (succ
);
890 succ
->m_offset
= next
->m_length
| __rtl_memory_last(succ
);
893 /* propagate 'last' bit */
894 next
->m_offset
|= __rtl_memory_last(prev
);
895 prev
->m_offset
&= ~0x1;
898 #define __rtl_memory_split(prev, next) \
900 (prev)->m_length -= (next)->m_length; \
901 if (!__rtl_memory_last((prev))) \
903 register memory_type * succ = queue_cast((next), (next)->m_length); \
904 succ->m_offset = (next)->m_length | __rtl_memory_last(succ); \
907 (next)->m_offset |= __rtl_memory_last((prev)); \
908 (prev)->m_offset &= ~0x1; \
910 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
913 * __rtl_memory_insert.
915 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
916 static void __rtl_memory_insert (memory_type
* memory
, sal_Size n
)
918 /* obtain queue head */
919 register memory_type
*head
;
921 head
= &(g_memory
.m_queue_head
[queue(n
)]);
922 DBG_MEMORY_VERIFY_CHAIN (head
);
924 /* insert at queue tail (first-in first-out) */
925 queue_insert_tail (head
, memory
);
928 #define __rtl_memory_insert(memory, n) \
930 register sal_Size h; \
933 queue_insert_tail (&(g_memory.m_queue_head[h]), (memory)); \
935 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
938 * __rtl_memory_resize.
940 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
941 static void __rtl_memory_resize (memory_type
* memory
, sal_Size n
)
943 register sal_Size k
= (memory
->m_length
- n
);
945 OSL_ENSURE(!(memory
->m_length
& 0x1),
946 "__rtl_memory_resize(): "
947 "internal logic error.");
949 if ((k
>= sizeof(memory_type
)) && (n
<= __T__
))
952 register memory_type
* remain
= queue_cast(memory
, n
);
954 remain
->m_length
= k
; remain
->m_offset
= n
;
955 __rtl_memory_split (memory
, remain
);
958 if (!__rtl_memory_last(remain
))
960 /* not last, verify used next entry */
961 register memory_type
*next
;
963 next
= queue_cast(remain
, remain
->m_length
);
964 DBG_MEMORY_VERIFY_CHAIN (next
);
966 OSL_POSTCOND(__rtl_memory_used(next
),
967 "__rtl_memory_resize(): "
968 "internal logic error.");
972 __rtl_memory_insert (remain
, k
);
973 DBG_MEMORY_VERIFY_QUEUE (remain
);
976 DBG_MEMORY_DEQUEUE(memory
->m_length
);
979 #define __rtl_memory_resize(memory, n) \
981 register sal_Size kn = ((memory)->m_length - (n)); \
982 if ((kn >= sizeof(memory_type)) && (n <= __T__)) \
984 register memory_type * remain = queue_cast((memory), (n)); \
986 remain->m_length = kn; remain->m_offset = (n); \
987 __rtl_memory_split ((memory), remain); \
989 __rtl_memory_insert (remain, kn); \
992 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
995 * __rtl_memory_dequeue.
997 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
998 static void __rtl_memory_dequeue (memory_type
**ppMemory
, sal_Size n
)
1000 register memory_type
*head
, *entry
;
1001 register sal_Size k
, m
= n
;
1003 OSL_PRECOND(!*ppMemory
, "__rtl_memory_dequeue(): internal logic error.");
1004 for (k
= queue(m
); k
< __N__
; k
++)
1006 /* first fit (equals best fit w/ ascending insert) */
1007 head
= &(g_memory
.m_queue_head
[k
]);
1008 for (entry
= head
->m_flink
; entry
!= head
; entry
= entry
->m_flink
)
1010 /* queue not empty */
1011 DBG_MEMORY_VERIFY_CHAIN (entry
);
1012 if (entry
->m_length
>= m
)
1015 DBG_MEMORY_VERIFY_QUEUE (entry
);
1016 queue_remove (entry
);
1025 head
= &(g_memory
.m_spare_head
);
1026 for (entry
= head
->m_flink
; entry
!= head
; entry
= entry
->m_flink
)
1028 /* queue not empty */
1029 DBG_MEMORY_VERIFY_CHAIN (entry
);
1030 if (entry
->m_length
>= m
)
1033 DBG_MEMORY_VERIFY_QUEUE (entry
);
1034 queue_remove (entry
);
1042 #if OSL_DEBUG_LEVEL > 0
1043 /* adjust for DBG_MEMORY_INSERT() overhead */
1044 m
+= sizeof(memory_type
);
1045 #endif /* OSL_DEBUG_LEVEL */
1047 k
= RTL_MEMORY_ALIGN((m
> __M__
) ? m
: __M__
, g_memory
.m_align
);
1048 if (!((entry
= RTL_MEMORY_ALLOC(k
)) == 0))
1050 entry
->m_length
= k
;
1051 entry
->m_offset
= 0x1; /* set 'last' bit */
1054 DBG_MEMORY_INSERT(ppMemory
);
1058 OSL_POSTCOND(*ppMemory
, "__rtl_memory_dequeue(): out of memory.");
1059 if ((entry
= *ppMemory
) != 0)
1062 __rtl_memory_resize (entry
, n
);
1064 /* fill w/ 'uninitialized' pattern */
1065 DBG_MEMORY_DEQFILL (entry
, __C__
, entry
->m_length
- __C__
);
1067 #if OSL_DEBUG_LEVEL > 1
1071 __dbg_memory_usage (&total
);
1073 #endif /* OSL_DEBUG_LEVEL */
1076 #define __rtl_memory_dequeue(ppMemory, n, label) \
1078 register memory_type *head, *entry; \
1079 register sal_Size h, m = (n); \
1082 for (; h < __N__; h++) \
1084 head = &(g_memory.m_queue_head[h]); \
1085 for (entry = head->m_flink; entry != head; entry = entry->m_flink) \
1087 if (entry->m_length >= m) \
1089 queue_remove (entry); \
1095 head = &(g_memory.m_spare_head); \
1096 for (entry = head->m_flink; entry != head; entry = entry->m_flink) \
1098 if (entry->m_length >= m) \
1100 queue_remove (entry); \
1105 h = RTL_MEMORY_ALIGN((m > __M__) ? m : __M__, g_memory.m_align); \
1106 if (!((entry = RTL_MEMORY_ALLOC(h)) == 0)) \
1108 entry->m_length = h; \
1109 entry->m_offset = 0x1; \
1115 __rtl_memory_resize (entry, (n)); \
1116 *(ppMemory) = entry; \
1119 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
1121 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
1122 #define RTL_MEMORY_DEQUEUE(m, n, l) __rtl_memory_dequeue((m), (n))
1124 #define RTL_MEMORY_DEQUEUE(m, n, l) __rtl_memory_dequeue(m, n, l)
1125 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
1128 * __rtl_memory_enqueue.
1130 #if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
1131 static void __rtl_memory_enqueue (memory_type
**ppMemory
)
1133 register memory_type
*head
= *ppMemory
;
1135 OSL_ENSURE(!__rtl_memory_used(head
),
1136 "__rtl_memory_enqueue(): "
1137 "internal logic error.");
1138 DBG_MEMORY_ENQUEUE (head
->m_length
);
1140 /* fill w/ 'deinitialized' pattern */
1141 DBG_MEMORY_ENQFILL (head
, __C__
, head
->m_length
- __C__
);
1143 /* try merge w/ next entry */
1144 if (!__rtl_memory_last(head
))
1146 /* not last, check next in chain */
1147 register memory_type
* next
;
1149 next
= queue_cast(head
, head
->m_length
);
1150 DBG_MEMORY_VERIFY_CHAIN (next
);
1152 if (!__rtl_memory_used(next
))
1155 DBG_MEMORY_VERIFY_QUEUE (next
);
1156 queue_remove (next
);
1159 __rtl_memory_merge (head
, next
);
1160 DBG_MEMORY_ENQFILL (next
, 0, sizeof(memory_type
));
1164 /* try merge w/ prev entry */
1165 if (__rtl_memory_offset(head
) > 0)
1167 /* not first, check prev in chain */
1168 register memory_type
* prev
;
1170 prev
= queue_cast(head
, -(__rtl_memory_offset(head
)));
1171 DBG_MEMORY_VERIFY_CHAIN (prev
);
1173 if (!__rtl_memory_used(prev
))
1176 DBG_MEMORY_VERIFY_QUEUE (prev
);
1177 queue_remove (prev
);
1180 __rtl_memory_merge (prev
, head
);
1181 DBG_MEMORY_ENQFILL (head
, 0, sizeof(memory_type
));
1186 if (!(head
->m_offset
== 0x1))
1188 /* page still used, enqueue */
1189 __rtl_memory_insert (head
, head
->m_length
);
1192 else if (head
->m_length
<= g_memory
.m_align
)
1194 /* small page unused, check spare page */
1195 register memory_type
* spare
;
1197 spare
= &(g_memory
.m_spare_head
);
1198 if (spare
->m_flink
== spare
)
1200 /* keep as spare page */
1201 queue_insert_tail (spare
, head
);
1205 if ((*ppMemory
= head
) != 0)
1207 /* page unused, remove */
1208 DBG_MEMORY_REMOVE(ppMemory
);
1212 #define __rtl_memory_enqueue(ppMemory) \
1214 register memory_type *head = *(ppMemory); \
1216 if (!__rtl_memory_last(head)) \
1218 register memory_type * next; \
1219 next = queue_cast(head, head->m_length); \
1220 if (!__rtl_memory_used(next)) \
1222 queue_remove (next); \
1223 __rtl_memory_merge (head, next); \
1227 if (__rtl_memory_offset(head) > 0) \
1229 register memory_type * prev; \
1230 prev = queue_cast(head, -(__rtl_memory_offset(head))); \
1231 if (!__rtl_memory_used(prev)) \
1233 queue_remove (prev); \
1234 __rtl_memory_merge (prev, head); \
1239 if (!(head->m_offset == 0x1)) \
1241 register memory_type * used = head; \
1242 __rtl_memory_insert (used, used->m_length); \
1245 else if (head->m_length <= g_memory.m_align) \
1247 register memory_type * spare; \
1248 spare = &(g_memory.m_spare_head); \
1249 if (spare->m_flink == spare) \
1251 queue_insert_tail (spare, head); \
1256 *(ppMemory) = head; \
1258 #endif /* OSL_DEBUG_LEVEL || PRODUCT */
1260 #define RTL_MEMORY_ENQUEUE(m) __rtl_memory_enqueue((m))
1262 #endif /* FORCE_SYSALLOC */
1264 /*===========================================================================
1266 * rtl_memory (manager) implementation.
1268 *=========================================================================*/
1270 * rtl_reallocateMemory.
1273 void* SAL_CALL
rtl_reallocateMemory_CUSTOM (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1275 memory_type
* memory
;
1279 register sal_Size datlen
;
1281 memory
= queue_cast(p
, -(__C__
)); p
= 0;
1282 n
= RTL_MEMORY_ALIGN(n
, __Q__
) + __C__
;
1285 DBG_MEMORY_VERIFY(memory
);
1287 /* clear 'used' bit */
1288 DBG_MEMORY_ENQUEUE (memory
->m_length
);
1289 memory
->m_length
&= ~0x1;
1291 /* amount of data to be moved or copied */
1292 datlen
= ((memory
->m_length
< n
) ? memory
->m_length
: n
);
1294 /* try merge w/ next entry */
1295 if (!__rtl_memory_last(memory
))
1297 /* not last, check next in chain */
1298 register memory_type
* next
;
1300 next
= queue_cast(memory
, memory
->m_length
);
1301 DBG_MEMORY_VERIFY_CHAIN(next
);
1303 if (!__rtl_memory_used(next
))
1306 DBG_MEMORY_VERIFY_QUEUE(next
);
1307 queue_remove (next
);
1310 __rtl_memory_merge (memory
, next
);
1314 /* try merge w/ prev entry */
1315 if (__rtl_memory_offset(memory
) > 0)
1317 /* not first, check prev in chain */
1318 register memory_type
* prev
;
1320 prev
= queue_cast(memory
, -(__rtl_memory_offset(memory
)));
1321 DBG_MEMORY_VERIFY_CHAIN (prev
);
1323 if (!__rtl_memory_used(prev
))
1325 /* prev not used, try merge, move */
1326 if ((memory
->m_length
+ prev
->m_length
) >= n
)
1329 DBG_MEMORY_VERIFY_QUEUE (prev
);
1330 queue_remove (prev
);
1333 __rtl_memory_merge (prev
, memory
);
1337 queue_cast(prev
, __C__
),
1338 queue_cast(memory
, __C__
),
1345 if (memory
->m_length
>= n
)
1347 /* adjust, set 'used' bit */
1348 __rtl_memory_resize (memory
, n
);
1349 memory
->m_length
|= 0x1;
1352 p
= queue_cast(memory
, __C__
);
1357 memory_type
* result
= 0;
1359 /* restore 'used' bit */
1360 DBG_MEMORY_DEQUEUE (memory
->m_length
);
1361 memory
->m_length
|= 0x80000000;
1363 RTL_MEMORY_DEQUEUE (&result
, n
, realloc_label_1
);
1366 /* set 'used' bit */
1367 result
->m_length
|= 0x1;
1371 queue_cast(result
, __C__
),
1372 queue_cast(memory
, __C__
),
1375 /* clear 'used' bit, enqueue */
1376 memory
->m_length
&= 0x7fffffff;
1377 RTL_MEMORY_ENQUEUE (&memory
);
1380 /* free memory page */
1381 RTL_MEMORY_FREE(memory
, memory
->m_length
);
1385 p
= queue_cast(result
, __C__
);
1394 n
= RTL_MEMORY_ALIGN(n
, __Q__
) + __C__
;
1397 RTL_MEMORY_DEQUEUE (&memory
, n
, realloc_label_2
);
1400 /* set 'used' bit */
1401 memory
->m_length
|= 0x1;
1404 p
= queue_cast(memory
, __C__
);
1411 memory
= queue_cast(p
, -(__C__
)); p
= 0;
1414 DBG_MEMORY_VERIFY(memory
);
1416 /* clear 'used' bit, enqueue */
1417 memory
->m_length
&= ~0x1;
1419 RTL_MEMORY_ENQUEUE (&memory
);
1422 /* free memory page */
1423 RTL_MEMORY_FREE(memory
, memory
->m_length
);
1431 void* SAL_CALL
rtl_reallocateMemory_SYSTEM (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1433 return realloc(p
, (sal_Size
)(n
));
1436 void* SAL_CALL
rtl_reallocateMemory (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1439 if (alloc_mode
== AMode_CUSTOM
) {
1440 return rtl_reallocateMemory_CUSTOM(p
,n
);
1442 if (alloc_mode
== AMode_SYSTEM
) {
1443 return rtl_reallocateMemory_SYSTEM(p
,n
);
1445 determine_alloc_mode();
1452 * rtl_allocateMemory.
1455 void* SAL_CALL
rtl_allocateMemory_CUSTOM (sal_Size n
) SAL_THROW_EXTERN_C()
1460 memory_type
* memory
= 0;
1461 n
= RTL_MEMORY_ALIGN(n
, __Q__
) + __C__
;
1464 RTL_MEMORY_DEQUEUE (&memory
, n
, alloc_label
);
1467 /* set 'used' bit */
1468 memory
->m_length
|= 0x1;
1471 p
= queue_cast(memory
, __C__
);
1479 void* SAL_CALL
rtl_allocateMemory_SYSTEM (sal_Size n
) SAL_THROW_EXTERN_C()
1481 return malloc((sal_Size
)(n
));
1484 void* SAL_CALL
rtl_allocateMemory (sal_Size n
) SAL_THROW_EXTERN_C()
1487 if (alloc_mode
== AMode_CUSTOM
) {
1488 return rtl_allocateMemory_CUSTOM(n
);
1490 if (alloc_mode
== AMode_SYSTEM
) {
1491 return rtl_allocateMemory_SYSTEM(n
);
1493 determine_alloc_mode();
1503 void SAL_CALL
rtl_freeMemory_CUSTOM (void * p
) SAL_THROW_EXTERN_C()
1507 memory_type
* memory
= queue_cast(p
, -(__C__
));
1510 DBG_MEMORY_VERIFY(memory
);
1512 /* clear 'used' bit, enqueue */
1513 memory
->m_length
&= ~0x1;
1515 RTL_MEMORY_ENQUEUE (&memory
);
1518 /* free memory page */
1519 RTL_MEMORY_FREE(memory
, memory
->m_length
);
1526 void SAL_CALL
rtl_freeMemory_SYSTEM (void * p
) SAL_THROW_EXTERN_C()
1531 void SAL_CALL
rtl_freeMemory (void * p
) SAL_THROW_EXTERN_C()
1534 if (alloc_mode
== AMode_CUSTOM
) {
1535 rtl_freeMemory_CUSTOM(p
);
1538 if (alloc_mode
== AMode_SYSTEM
) {
1539 rtl_freeMemory_SYSTEM(p
);
1542 determine_alloc_mode();
1548 * rtl_allocateZeroMemory.
1551 void* SAL_CALL
rtl_allocateZeroMemory_CUSTOM (sal_Size n
) SAL_THROW_EXTERN_C()
1556 memory_type
* memory
= 0;
1557 n
= RTL_MEMORY_ALIGN(n
, __Q__
) + __C__
;
1560 RTL_MEMORY_DEQUEUE (&memory
, n
, alloc_label
); /* NYI: demand zero */
1563 /* zero, set 'used' bit */
1564 memset ((char*)memory
+ __C__
, 0, memory
->m_length
- __C__
);
1565 memory
->m_length
|= 0x1;
1568 p
= queue_cast(memory
, __C__
);
1576 void* SAL_CALL
rtl_allocateZeroMemory_SYSTEM (sal_Size n
) SAL_THROW_EXTERN_C()
1578 return calloc((sal_Size
)(n
), 1);
1581 void* SAL_CALL
rtl_allocateZeroMemory (sal_Size n
) SAL_THROW_EXTERN_C()
1584 if (alloc_mode
== AMode_CUSTOM
) {
1585 return rtl_allocateZeroMemory_CUSTOM(n
);
1587 if (alloc_mode
== AMode_SYSTEM
) {
1588 return rtl_allocateZeroMemory_SYSTEM(n
);
1590 determine_alloc_mode();
1596 * rtl_freeZeroMemory.
1599 void SAL_CALL
rtl_freeZeroMemory_CUSTOM (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1601 (void) n
; /* unused */
1604 memory_type
* memory
= queue_cast(p
, -(__C__
));
1607 DBG_MEMORY_VERIFY(memory
);
1609 /* clear 'used' bit, zero, enqueue */
1610 memory
->m_length
&= ~0x1;
1611 memset ((char*)memory
+ __C__
, 0, memory
->m_length
- __C__
);
1613 RTL_MEMORY_ENQUEUE (&memory
); /* NYI: demand zero */
1616 /* free memory page */
1617 RTL_MEMORY_FREE(memory
, memory
->m_length
);
1624 void SAL_CALL
rtl_freeZeroMemory_SYSTEM (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1633 void SAL_CALL
rtl_freeZeroMemory (void * p
, sal_Size n
) SAL_THROW_EXTERN_C()
1636 if (alloc_mode
== AMode_CUSTOM
) {
1637 rtl_freeZeroMemory_CUSTOM(p
,n
);
1640 if (alloc_mode
== AMode_SYSTEM
) {
1641 rtl_freeZeroMemory_SYSTEM(p
,n
);
1644 determine_alloc_mode();
1648 /*===========================================================================
1652 *=========================================================================*/