3
* Copyright (C) 2002, AVM GmbH. All rights reserved.
5
* This Software is free software. You can redistribute and/or
6
* modify such free software under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* The free software is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this Software; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA, or see
18
* http://www.opensource.org/licenses/lgpl-license.html
20
* Contact: AVM GmbH, Alt-Moabit 95, 10559 Berlin, Germany, email: info@avm.de
23
#include <linux/slab.h>
24
#include <linux/string.h>
25
#include <linux/vmalloc.h>
26
#include <linux/kernel.h>
34
/*---------------------------------------------------------------------------*\
35
\*---------------------------------------------------------------------------*/
42
/*---------------------------------------------------------------------------*\
43
\*---------------------------------------------------------------------------*/
44
#if defined (TOOLS_PTR_QUEUE)
47
unsigned head, tail, mask;
55
/*---------------------------------------------------------------------------*\
56
\*---------------------------------------------------------------------------*/
57
typedef struct __hdr {
61
#if defined (TOOLS_FREE_CATCH)
69
/*---------------------------------------------------------------------------*\
70
\*---------------------------------------------------------------------------*/
71
#define KMALLOC_LIMIT 131072
74
#define TYPE_KMALLOCED 'k'
75
#define TYPE_VMALLOCED 'v'
76
#define TYPE_SMALLOCED 's'
78
#define ALLOC_NORMAL 0
79
#define ALLOC_SPECIAL 1
82
#define PATCH(n) sizeof(header_t)+sizeof(unsigned)+((n)?(n):1)
84
#define PATCH(n) sizeof(header_t)+((n)?(n):1)
87
static void * halloc (unsigned, int, int);
89
#define __ALLOC(s,p) halloc((s),(p),ALLOC_NORMAL)
91
/*---------------------------------------------------------------------------*\
92
\*---------------------------------------------------------------------------*/
93
#if defined (TOOLS_NOMEM_HANDLER)
94
static nomem_handler_t handler = NULL;
97
#if defined (TOOLS_SUB_ALLOC)
98
static void * lib_heap_base = NULL;
99
static unsigned lib_heap_size = 0;
102
/*---------------------------------------------------------------------------*\
103
\*---------------------------------------------------------------------------*/
104
#if !defined (NDEBUG)
105
#include <asm/atomic.h>
106
#include <linux/spinlock.h>
108
#define FENCE_TAG 0xDEADBEEF
109
#define FENCE1_OK(h,m) ((h)->tag==FENCE_TAG)
110
#define FENCE2_OK(h,m) (*(unsigned *)(((char *) m)+(h)->size)==FENCE_TAG)
112
static unsigned alloc_count = 0;
113
static spinlock_t track_lock = SPIN_LOCK_UNLOCKED;
115
#if !defined (NDEBUG) && defined (LOG_TIMER)
116
static struct timeval zero_time;
120
/*---------------------------------------------------------------------------*\
121
\*---------------------------------------------------------------------------*/
122
#if !defined (NDEBUG)
123
static inline void track_alloc (header_t * hdr) {
126
#if defined (LOG_ALLOC)
127
LOG("ALLOC: %p, %u, type %c\n", hdr + 1, hdr->size, hdr->type);
129
spin_lock_irqsave (&track_lock, flags);
130
alloc_count += hdr->size;
132
spin_unlock_irqrestore (&track_lock, flags);
136
/*---------------------------------------------------------------------------*\
137
\*---------------------------------------------------------------------------*/
138
#if !defined (NDEBUG)
139
static inline void track_free (header_t * hdr) {
142
#if defined (LOG_ALLOC)
143
LOG("FREE: %p, %u, type %c\n", hdr + 1, hdr->size, hdr->type);
145
spin_lock_irqsave (&track_lock, flags);
146
info (alloc_count >= hdr->size);
147
alloc_count -= hdr->size;
149
spin_unlock_irqrestore (&track_lock, flags);
153
/*---------------------------------------------------------------------------*\
154
\*---------------------------------------------------------------------------*/
155
#if defined (TOOLS_SUB_ALLOC)
156
unsigned libheap_init (unsigned heap_size) {
157
void * heap_base = NULL;
159
assert (lib_heap_base == NULL);
160
assert (heap_size > MIN_LIB_HEAP_SIZE);
162
heap_base = halloc (heap_size, GFP_ATOMIC, ALLOC_SPECIAL);
163
info (heap_base != NULL);
164
if (NULL != heap_base) {
165
lib_heap_base = heap_base;
166
lib_heap_size = heap_size;
167
(*capi_lib->lib_heap_init) (heap_base, heap_size);
171
} while (heap_size > 0);
176
/*---------------------------------------------------------------------------*\
177
\*---------------------------------------------------------------------------*/
178
#if defined (TOOLS_SUB_ALLOC)
179
void libheap_exit (void) {
181
assert (lib_heap_base != NULL);
182
(*capi_lib->lib_heap_exit) (lib_heap_base);
183
hfree (lib_heap_base);
184
lib_heap_base = NULL;
189
/*---------------------------------------------------------------------------*\
190
\*---------------------------------------------------------------------------*/
191
#if defined (TOOLS_NOMEM_HANDLER)
192
nomem_handler_t hset_handler (nomem_handler_t hndf) {
193
nomem_handler_t oldf = handler;
200
/*---------------------------------------------------------------------------*\
201
\*---------------------------------------------------------------------------*/
202
#if !defined (NDEBUG)
203
unsigned hallocated (void) {
209
/*---------------------------------------------------------------------------*\
210
\*---------------------------------------------------------------------------*/
211
#if !defined (NDEBUG)
212
int hvalid (void * mem) {
217
hdr = ((header_t *) mem) - 1;
218
flag = FENCE1_OK(hdr, mem) && FENCE2_OK(hdr, mem);
224
/*---------------------------------------------------------------------------*\
225
\*---------------------------------------------------------------------------*/
226
void * hmalloc (unsigned size) {
228
return __ALLOC(size, GFP_ATOMIC);
231
/*---------------------------------------------------------------------------*\
232
\*---------------------------------------------------------------------------*/
233
void * hcalloc (unsigned size) {
236
mem = __ALLOC(size, GFP_ATOMIC);
237
if ((mem != NULL) && (size != 0)) {
238
lib_memset (mem, 0, size);
243
/*---------------------------------------------------------------------------*\
244
\*---------------------------------------------------------------------------*/
245
void * hmalloc_kernel (unsigned size) {
247
return __ALLOC(size, GFP_KERNEL);
250
/*---------------------------------------------------------------------------*\
251
\*---------------------------------------------------------------------------*/
252
void * hcalloc_kernel (unsigned size) {
255
mem = __ALLOC(size, GFP_KERNEL);
256
if ((mem != NULL) && (size != 0)) {
257
lib_memset (mem, 0, size);
262
/*---------------------------------------------------------------------------*\
263
\*---------------------------------------------------------------------------*/
264
static void * halloc (unsigned size, int prio, int mode) {
271
if (n <= KMALLOC_LIMIT) {
272
hdr = kmalloc (n, prio);
273
type = TYPE_KMALLOCED;
275
#if defined (TOOLS_SUB_ALLOC)
276
if (ALLOC_NORMAL == mode) {
277
info (lib_heap_base != NULL);
278
assert (capi_lib->lib_heap_alloc != NULL);
279
hdr = (* capi_lib->lib_heap_alloc) (lib_heap_base, n);
280
type = TYPE_SMALLOCED;
282
assert (ALLOC_SPECIAL == mode);
284
type = TYPE_VMALLOCED;
288
type = TYPE_VMALLOCED;
292
/* Accounting & debugging */
296
"Memory request (%u/%u bytes) failed.\n",
301
#if defined (TOOLS_NOMEM_HANDLER)
302
if (handler != NULL) {
307
mem = (void *) (hdr + 1);
309
#if !defined (NDEBUG)
310
hdr->size = size ? size : 1;
311
hdr->tag = FENCE_TAG;
312
#if defined (TOOLS_FREE_CATCH)
315
* (unsigned *) (((char *) mem) + size) = FENCE_TAG;
322
/*---------------------------------------------------------------------------*\
323
\*---------------------------------------------------------------------------*/
324
void hfree (void * mem) {
330
/* Accounting & checking */
331
hdr = ((header_t *) mem) - 1;
332
#if !defined (NDEBUG)
333
if (!(FENCE1_OK(hdr, mem) && FENCE2_OK(hdr, mem))) {
335
"FENCE VIOLATED (%u bytes @ %p)!\n",
344
#if !defined (TOOLS_FREE_CATCH)
356
#if defined (TOOLS_SUB_ALLOC)
358
assert (capi_lib->lib_heap_free != NULL);
359
info (lib_heap_base != NULL);
360
(* capi_lib->lib_heap_free) (lib_heap_base, hdr);
365
if (hdr->nfree != 0) {
367
"ALREADY FREED (%u bytes @ %p)!\n",
378
/*---------------------------------------------------------------------------*\
379
\*-T-------------------------------------------------------------------------*/
381
#if !defined (NDEBUG) && defined (LOG_TIMER)
383
#include <linux/time.h>
385
void setup_timer (dbg_timer * t, long dsec, long dusec) {
388
lib_memset (&t->t, 0, sizeof (t->t));
390
t->d.tv_usec = dusec;
393
/*---------------------------------------------------------------------------*\
394
\*---------------------------------------------------------------------------*/
395
int check_timer (dbg_timer * t) {
398
struct timeval delta;
401
do_gettimeofday (&now);
402
timeval_less (now, zero_time, &delta);
404
timeval_less (now, t->t, &delta);
405
if ((delta.tv_sec > t->d.tv_sec)
406
|| ((delta.tv_sec == t->d.tv_sec) && (delta.tv_usec > t->d.tv_usec))
409
"Timer '%s' exceeded: %ld s, %ld �s\n",
419
/*---------------------------------------------------------------------------*\
420
\*---------------------------------------------------------------------------*/
421
int check_timer_cb (dbg_timer * t, void (* callback) (dbg_timer *, struct timeval *)) {
424
struct timeval delta;
427
do_gettimeofday (&now);
428
timeval_less (now, zero_time, &delta);
430
timeval_less (now, t->t, &delta);
431
if ((delta.tv_sec > t->d.tv_sec)
432
|| ((delta.tv_sec == t->d.tv_sec) && (delta.tv_usec > t->d.tv_usec))
434
if (callback != NULL) {
435
(*callback) (t, &delta);
440
} /* check_timer_cb */
442
/*---------------------------------------------------------------------------*\
443
\*---------------------------------------------------------------------------*/
444
void touch_timer (dbg_timer * t) {
445
struct timeval temp, delta;
448
do_gettimeofday (&temp);
449
timeval_less (temp, zero_time, &delta);
453
/*---------------------------------------------------------------------------*\
454
\*---------------------------------------------------------------------------*/
455
void start_watch (dbg_timer * w) {
456
struct timeval temp, delta;
459
do_gettimeofday (&temp);
460
timeval_less (temp, zero_time, &delta);
464
/*---------------------------------------------------------------------------*\
465
\*---------------------------------------------------------------------------*/
466
void stop_watch (dbg_timer * w) {
467
struct timeval temp, delta;
470
do_gettimeofday (&temp);
471
timeval_less (temp, zero_time, &delta);
473
timeval_less (temp, w->t, &delta);
477
/*---------------------------------------------------------------------------*\
478
\*---------------------------------------------------------------------------*/
479
int timers_start (void) {
481
do_gettimeofday (&zero_time);
485
/*---------------------------------------------------------------------------*\
486
\*---------------------------------------------------------------------------*/
487
void timers_stop (void) {
491
#endif /* !NDEBUG && LOG_TIMER */
493
/*---------------------------------------------------------------------------*\
494
\*-M-------------------------------------------------------------------------*/
495
void vlprintf (const char * level, const char * fmt, va_list args) {
496
static char line[1024];
498
vsnprintf (line, sizeof (line), fmt, args);
499
printk ("%s%s: %s", level, TARGET, line);
502
/*---------------------------------------------------------------------------*\
503
\*---------------------------------------------------------------------------*/
504
void lprintf (const char * level, const char * fmt, ...) {
507
va_start (args, fmt);
508
vlprintf (level, fmt, args);
512
/*---------------------------------------------------------------------------*\
513
\*---------------------------------------------------------------------------*/
514
void message (const char * fmt, ...) {
517
va_start (args, fmt);
518
vlprintf (KERN_INFO, fmt, args);
522
/*---------------------------------------------------------------------------*\
523
\*-L-------------------------------------------------------------------------*/
524
int lock_init (lock_t * plock) {
527
assert (plock != NULL);
528
if (NULL == (tmp = (lock_t) hcalloc (sizeof (struct __lock)))) {
529
ERROR("Could not allocate lock structure!!!\n");
532
tmp->lock = SPIN_LOCK_UNLOCKED;
537
/*---------------------------------------------------------------------------*\
538
\*---------------------------------------------------------------------------*/
539
void lock_exit (lock_t * plock) {
541
assert (plock != NULL);
542
assert (*plock != NULL);
543
assert (!spin_is_locked (&(*plock)->lock));
548
/*---------------------------------------------------------------------------*\
549
\*---------------------------------------------------------------------------*/
550
void lock (lock_t lp) {
551
unsigned long local_flags;
554
spin_lock_irqsave (&lp->lock, local_flags);
555
lp->flags = local_flags;
558
/*---------------------------------------------------------------------------*\
559
\*---------------------------------------------------------------------------*/
560
void unlock (lock_t lp) {
563
spin_unlock_irqrestore (&lp->lock, lp->flags);
566
/*---------------------------------------------------------------------------*\
567
\*-Q-------------------------------------------------------------------------*/
568
#if defined (TOOLS_PTR_QUEUE)
569
ptr_queue_p q_make (unsigned max) {
573
if (NULL == (qp = (ptr_queue_p) hmalloc (sizeof (ptr_queue_t)))) {
576
if (NULL == (qp->item = (void **) hmalloc (max * sizeof (void *)))) {
584
assert (mask == max);
594
/*---------------------------------------------------------------------------*\
595
\*---------------------------------------------------------------------------*/
596
void q_remove (ptr_queue_p * qpp) {
599
assert (qpp != NULL);
602
assert (qp->item != NULL);
603
if (qp->bptr != NULL) {
611
/*---------------------------------------------------------------------------*\
612
\*---------------------------------------------------------------------------*/
613
void q_reset (ptr_queue_p qp) {
616
qp->head = qp->tail = 0;
620
/*---------------------------------------------------------------------------*\
621
\*---------------------------------------------------------------------------*/
622
int q_attach_mem (ptr_queue_p qp, unsigned n, unsigned len) {
626
assert (qp->bptr == 0);
627
assert ((n * len) != 0);
628
if (NULL == (buf = hmalloc (n * len))) {
637
/*---------------------------------------------------------------------------*\
638
\*---------------------------------------------------------------------------*/
639
int q_enqueue (ptr_queue_p qp, void * p) {
645
assert (qp->head < qp->size);
646
qp->item[qp->head++] = p;
647
qp->head &= qp->mask;
648
assert (qp->head < qp->size);
653
/*---------------------------------------------------------------------------*\
654
\*---------------------------------------------------------------------------*/
655
int q_enqueue_mem (ptr_queue_p qp, void * m, unsigned len) {
660
assert (qp->bptr != NULL);
661
assert (qp->blen >= len);
665
assert (qp->head < qp->size);
667
qp->head &= qp->mask;
668
qp->item[ix] = mp = &qp->bptr[ix * len];
670
lib_memcpy (mp, m, len);
671
assert (qp->head < qp->size);
674
} /* q_enqueue_mem */
676
/*---------------------------------------------------------------------------*\
677
\*---------------------------------------------------------------------------*/
678
int q_dequeue (ptr_queue_p qp, void ** pp) {
681
if (qp->free == qp->size) {
684
assert (qp->tail < qp->size);
686
*pp = qp->item[qp->tail++];
687
qp->tail &= qp->mask;
688
assert (qp->tail < qp->size);
693
/*---------------------------------------------------------------------------*\
694
\*---------------------------------------------------------------------------*/
695
int q_peek (ptr_queue_p qp, void ** pp) {
698
if (qp->free == qp->size) {
701
assert (qp->tail < qp->size);
703
*pp = qp->item[qp->tail];
707
/*---------------------------------------------------------------------------*\
708
\*---------------------------------------------------------------------------*/
709
unsigned q_get_count (ptr_queue_p qp) {
712
return qp->size - qp->free;
716
/*---------------------------------------------------------------------------*\
717
\*---------------------------------------------------------------------------*/
718
#if defined (TOOLS_MEM_DUMP)
725
unsigned max, min, idx;
726
unsigned char * data = (unsigned char *) mem;
727
char hex[50], chr[20];
729
lprintf (KERN_INFO, "Memory dump %s:\n", msg);
732
max = ((min + 16) > len ? len : min + 16);
734
while ((min + idx) < max) {
735
snprintf (hex + 3 * idx, 4, "%02x ", *data);
736
snprintf (chr + idx, 2, "%c", ((' ' <= *data) &&
737
(*data <= '~')) ? *data : '.');
742
lib_strcpy (hex + 3 * idx++, " ");
744
lprintf (KERN_INFO, "%08x: %s %s\n", min + start, hex, chr);
750
/*---------------------------------------------------------------------------*\
751
\*---------------------------------------------------------------------------*/
753
__attr void _OSassert (void * exp, void * file, unsigned line) {
755
message ("assert (%s) in %s(%u)\n", exp, file, line);
758
__attr void _OSinfo (void * exp, void * file, unsigned line) {
760
message ("info (%s) in %s(%u)\n", exp, file, line);
764
/*---------------------------------------------------------------------------*\
765
\*---------------------------------------------------------------------------*/