hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (C) 2001,2002,2003 Philippe Gerum <rpm@xenomai.org>.
 *
 * Xenomai is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * Xenomai is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Xenomai; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
#ifndef _COBALT_KERNEL_HEAP_H
#define _COBALT_KERNEL_HEAP_H
 
#include <linux/string.h>
#include <linux/rbtree.h>
#include <cobalt/kernel/lock.h>
#include <cobalt/kernel/list.h>
#include <cobalt/uapi/kernel/types.h>
#include <cobalt/uapi/kernel/heap.h>
 
/**
 * @addtogroup cobalt_core_heap
 * @{
 */
 
#define XNHEAP_PAGE_SHIFT    9 /* 2^9 => 512 bytes */
#define XNHEAP_PAGE_SIZE    (1UL << XNHEAP_PAGE_SHIFT)
#define XNHEAP_PAGE_MASK    (~(XNHEAP_PAGE_SIZE - 1))
#define XNHEAP_MIN_LOG2        4 /* 16 bytes */
/*
 * Use bucketed memory for sizes between 2^XNHEAP_MIN_LOG2 and
 * 2^(XNHEAP_PAGE_SHIFT-1).
 */
#define XNHEAP_MAX_BUCKETS    (XNHEAP_PAGE_SHIFT - XNHEAP_MIN_LOG2)
#define XNHEAP_MIN_ALIGN    (1U << XNHEAP_MIN_LOG2)
/* Maximum size of a heap (4Gb - PAGE_SIZE). */
#define XNHEAP_MAX_HEAPSZ    (4294967295U - PAGE_SIZE + 1)
/* Bits we need for encoding a page # */
#define XNHEAP_PGENT_BITS      (32 - XNHEAP_PAGE_SHIFT)
/* Each page is represented by a page map entry. */
#define XNHEAP_PGMAP_BYTES    sizeof(struct xnheap_pgentry)
 
struct xnheap_pgentry {
   /* Linkage in bucket list. */
   unsigned int prev : XNHEAP_PGENT_BITS;
   unsigned int next : XNHEAP_PGENT_BITS;
   /*  page_list or log2. */
   unsigned int type : 6;
   /*
    * We hold either a spatial map of busy blocks within the page
    * for bucketed memory (up to 32 blocks per page), or the
    * overall size of the multi-page block if entry.type ==
    * page_list.
    */
   union {
       u32 map;
       u32 bsize;
   };
};
 
/*
 * A range descriptor is stored at the beginning of the first page of
 * a range of free pages. xnheap_range.size is nrpages *
 * XNHEAP_PAGE_SIZE. Ranges are indexed by address and size in
 * rbtrees.
 */
struct xnheap_range {
   struct rb_node addr_node;
   struct rb_node size_node;
   size_t size;
};
 
struct xnheap {
   void *membase;
   struct rb_root addr_tree;
   struct rb_root size_tree;
   struct xnheap_pgentry *pagemap;
   size_t usable_size;
   size_t used_size;
   u32 buckets[XNHEAP_MAX_BUCKETS];
   char name[XNOBJECT_NAME_LEN];
   DECLARE_XNLOCK(lock);
   struct list_head next;
};
 
extern struct xnheap cobalt_heap;
 
#define xnmalloc(size)     xnheap_alloc(&cobalt_heap, size)
#define xnfree(ptr)        xnheap_free(&cobalt_heap, ptr)
 
static inline void *xnheap_get_membase(const struct xnheap *heap)
{
   return heap->membase;
}
 
static inline
size_t xnheap_get_size(const struct xnheap *heap)
{
   return heap->usable_size;
}
 
static inline
size_t xnheap_get_used(const struct xnheap *heap)
{
   return heap->used_size;
}
 
static inline
size_t xnheap_get_free(const struct xnheap *heap)
{
   return heap->usable_size - heap->used_size;
}
 
int xnheap_init(struct xnheap *heap,
       void *membase, size_t size);
 
void xnheap_destroy(struct xnheap *heap);
 
void *xnheap_alloc(struct xnheap *heap, size_t size);
 
void xnheap_free(struct xnheap *heap, void *block);
 
ssize_t xnheap_check_block(struct xnheap *heap, void *block);
 
void xnheap_set_name(struct xnheap *heap,
            const char *name, ...);
 
void *xnheap_vmalloc(size_t size);
 
void xnheap_vfree(void *p);
 
static inline void *xnheap_zalloc(struct xnheap *heap, size_t size)
{
   void *p;
 
   p = xnheap_alloc(heap, size);
   if (p)
       memset(p, 0, size);
 
   return p;
}
 
static inline char *xnstrdup(const char *s)
{
   char *p;
 
   p = xnmalloc(strlen(s) + 1);
   if (p == NULL)
       return NULL;
 
   return strcpy(p, s);
}
 
#ifdef CONFIG_XENO_OPT_VFILE
void xnheap_init_proc(void);
void xnheap_cleanup_proc(void);
#else /* !CONFIG_XENO_OPT_VFILE */
static inline void xnheap_init_proc(void) { }
static inline void xnheap_cleanup_proc(void) { }
#endif /* !CONFIG_XENO_OPT_VFILE */
 
/** @} */
 
#endif /* !_COBALT_KERNEL_HEAP_H */