]>
Commit | Line | Data |
---|---|---|
3affbe6d BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 | * or http://www.opensolaris.org/os/licensing. | |
10 | * See the License for the specific language governing permissions | |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | ||
22 | /* | |
23 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved. | |
24 | * Use is subject to license terms. | |
25 | */ | |
26 | ||
e5dc681a | 27 | |
3affbe6d BB |
28 | |
29 | #include <sys/stropts.h> | |
30 | #include <sys/isa_defs.h> | |
31 | #include <sys/nvpair.h> | |
32 | #include <sys/sysmacros.h> | |
33 | #if defined(_KERNEL) && !defined(_BOOT) | |
34 | #include <sys/varargs.h> | |
35 | #else | |
36 | #include <stdarg.h> | |
37 | #include <strings.h> | |
38 | #endif | |
39 | ||
40 | /* | |
41 | * This allocator is very simple. | |
42 | * - it uses a pre-allocated buffer for memory allocations. | |
43 | * - it does _not_ free memory in the pre-allocated buffer. | |
44 | * | |
4e33ba4c | 45 | * The reason for the selected implementation is simplicity. |
3affbe6d BB |
46 | * This allocator is designed for the usage in interrupt context when |
47 | * the caller may not wait for free memory. | |
48 | */ | |
49 | ||
50 | /* pre-allocated buffer for memory allocations */ | |
51 | typedef struct nvbuf { | |
52 | uintptr_t nvb_buf; /* address of pre-allocated buffer */ | |
53 | uintptr_t nvb_lim; /* limit address in the buffer */ | |
54 | uintptr_t nvb_cur; /* current address in the buffer */ | |
55 | } nvbuf_t; | |
56 | ||
57 | /* | |
58 | * Initialize the pre-allocated buffer allocator. The caller needs to supply | |
59 | * | |
60 | * buf address of pre-allocated buffer | |
61 | * bufsz size of pre-allocated buffer | |
62 | * | |
63 | * nv_fixed_init() calculates the remaining members of nvbuf_t. | |
64 | */ | |
65 | static int | |
66 | nv_fixed_init(nv_alloc_t *nva, va_list valist) | |
67 | { | |
68 | uintptr_t base = va_arg(valist, uintptr_t); | |
69 | uintptr_t lim = base + va_arg(valist, size_t); | |
70 | nvbuf_t *nvb = (nvbuf_t *)P2ROUNDUP(base, sizeof (uintptr_t)); | |
71 | ||
72 | if (base == 0 || (uintptr_t)&nvb[1] > lim) | |
73 | return (EINVAL); | |
74 | ||
75 | nvb->nvb_buf = (uintptr_t)&nvb[0]; | |
76 | nvb->nvb_cur = (uintptr_t)&nvb[1]; | |
77 | nvb->nvb_lim = lim; | |
78 | nva->nva_arg = nvb; | |
79 | ||
80 | return (0); | |
81 | } | |
82 | ||
83 | static void * | |
84 | nv_fixed_alloc(nv_alloc_t *nva, size_t size) | |
85 | { | |
86 | nvbuf_t *nvb = nva->nva_arg; | |
87 | uintptr_t new = nvb->nvb_cur; | |
88 | ||
89 | if (size == 0 || new + size > nvb->nvb_lim) | |
90 | return (NULL); | |
91 | ||
92 | nvb->nvb_cur = P2ROUNDUP(new + size, sizeof (uintptr_t)); | |
93 | ||
94 | return ((void *)new); | |
95 | } | |
96 | ||
97 | /*ARGSUSED*/ | |
98 | static void | |
99 | nv_fixed_free(nv_alloc_t *nva, void *buf, size_t size) | |
100 | { | |
101 | /* don't free memory in the pre-allocated buffer */ | |
102 | } | |
103 | ||
104 | static void | |
105 | nv_fixed_reset(nv_alloc_t *nva) | |
106 | { | |
107 | nvbuf_t *nvb = nva->nva_arg; | |
108 | ||
109 | nvb->nvb_cur = (uintptr_t)&nvb[1]; | |
110 | } | |
111 | ||
112 | const nv_alloc_ops_t nv_fixed_ops_def = { | |
113 | nv_fixed_init, /* nv_ao_init() */ | |
114 | NULL, /* nv_ao_fini() */ | |
115 | nv_fixed_alloc, /* nv_ao_alloc() */ | |
116 | nv_fixed_free, /* nv_ao_free() */ | |
117 | nv_fixed_reset /* nv_ao_reset() */ | |
118 | }; | |
119 | ||
120 | const nv_alloc_ops_t *nv_fixed_ops = &nv_fixed_ops_def; | |
c28b2279 BB |
121 | |
122 | #if defined(_KERNEL) && defined(HAVE_SPL) | |
123 | EXPORT_SYMBOL(nv_fixed_ops); | |
124 | #endif |