|
|
1.1 root 1: /*
2: * Copyright (c) 1999, 2000 University of Utah and the Flux Group.
3: * All rights reserved.
4: *
5: * This file is part of the Flux OSKit. The OSKit is free software, also known
6: * as "open source;" you can redistribute it and/or modify it under the terms
7: * of the GNU General Public License (GPL), version 2, as published by the Free
8: * Software Foundation (FSF). To explore alternate licensing terms, contact
9: * the University of Utah at [email protected] or +1-801-585-3271.
10: *
11: * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
12: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13: * FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
14: * received a copy of the GPL along with the OSKit; see the file COPYING. If
15: * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
16: */
17:
18: #include <oskit/com.h>
19: #include <oskit/com/mem.h>
20: #include <oskit/com/services.h>
21: #include <oskit/dev/dev.h>
22: #include <oskit/dev/osenv_mem.h>
23:
24: #include <oskit/lmm.h>
25: #include <oskit/machine/base_vm.h>
26: #include <oskit/machine/physmem.h>
27: #include <oskit/machine/phys_lmm.h>
28:
29: #include <string.h>
30:
31: #include <cpus.h>
32: #include "lock.h"
33: #include "kalloc.h"
34: #include "zalloc.h"
35: #include "assert.h"
36: #include <machine/spl.h>
37:
38: #include <vm/vm_kern.h>
39:
40: #include "ds_oskit.h"
41:
42: #define in_oskit_interrupt (nested_pic_mask != 0)
43: extern unsigned int nested_pic_mask; /* osenv_irq.c */
44:
45: decl_simple_lock_data(, phys_lmm_lock)
46: decl_simple_lock_data(extern, vm_page_queue_free_lock)
47:
48: extern int vm_page_unqueued_count; /* vm_resident.c */
49: extern zone_t vm_page_zone;
50: extern vm_offset_t virtual_space_start;
51: extern vm_offset_t virtual_space_end;
52:
53: int lmm_wants_pages;
54:
55: #define debug_protect_page(p) ((void)(p))
56: #define debug_unprotect_page(p) ((void)(p))
57:
58:
59: /* Update the VM system's counts of free pages in the LMM.
60: Called at sploskit with phys_lmm_lock held. */
61: static void
62: update_counts (void)
63: {
64: vm_page_unqueued_count = atop (lmm_avail (&malloc_lmm, 0));
65: }
66:
67:
68: void *
69: alloc_for_oskit (oskit_size_t size, osenv_memflags_t flags, unsigned align)
70: {
71: kern_return_t kr;
72: lmm_flags_t lmm_flags;
73:
74: assert (align <= size);
75:
76: if (flags & OSENV_AUTO_SIZE)
77: {
78: oskit_size_t *p;
79: size += sizeof (oskit_size_t);
80: if (align > sizeof (oskit_size_t))
81: panic ("autosize + align %u", align);
82: /* XXX how would I recover the beginning of the block in free?
83: size += align - sizeof (oskit_size_t);
84: */
85: else
86: align = sizeof (oskit_size_t);
87: p = alloc_for_oskit (size, flags &~ OSENV_AUTO_SIZE, align);
88: if (p == 0)
89: return 0;
90: p = (void *) (((oskit_addr_t) (p + 1) + align - 1) &~ (align - 1));
91: p[-1] = size;
92: return p;
93: }
94:
95: lmm_flags = (((flags & OSENV_ISADMA_MEM) ? LMMF_16MB : 0)
96: | ((flags & OSENV_X861MB_MEM) ? LMMF_1MB : 0));
97:
98: if (lmm_flags != 0)
99: assert (flags & OSENV_VIRT_EQ_PHYS);
100:
101: if (mach_osenv == 0)
102: /* This is early oskit startup code before the kernel is set up.
103: Always go directly to physical memory. */
104: flags |= OSENV_VIRT_EQ_PHYS|OSENV_PHYS_WIRED|OSENV_PHYS_CONTIG;
105:
106: if (in_oskit_interrupt)
107: /* The oskit documentation says an interrupt caller must set the flag. */
108: assert (flags & OSENV_NONBLOCKING);
109:
110: if (!(flags & (OSENV_NONBLOCKING|OSENV_PHYS_WIRED)))
111: {
112: /* Unwired virtual memory will do. */
113:
114: if (size < PAGE_SIZE)
115: /* For less than a page we don't want to waste partial pages,
116: and we don't want to bother with a second-tier allocator
117: for virtual memory, so just give him wired memory. */
118: return (void *) kalloc (size);
119: else
120: {
121: vm_offset_t addr;
122: kr = kmem_alloc_pageable (kernel_map, &addr, size);
123: return kr ? 0 : (void *) addr;
124: }
125: }
126:
127: if (!(flags & (OSENV_VIRT_EQ_PHYS|OSENV_NONBLOCKING))
128: && (!(flags & OSENV_PHYS_CONTIG) || size <= PAGE_SIZE))
129: {
130: /* Wired virtual memory will do. */
131: return (void *) kalloc (size);
132: }
133:
134: /* We need physically contiguous memory. This we get directly from the
135: lmm, which might also be used by vm_page_grab. All users of the lmm
136: must go to sploskit or above and take the phys_lmm_lock. This blocks
137: out any interrupts that might go to the oskit (and get us here). */
138: while (1)
139: {
140: spl_t s;
141: void *block;
142:
143: s = sploskit ();
144: simple_lock (&phys_lmm_lock);
145:
146: if (align)
147: block = lmm_alloc_aligned (&malloc_lmm, size, lmm_flags,
148: ffs (align) - 1, 0);
149: else
150: block = lmm_alloc (&malloc_lmm, size, lmm_flags);
151:
152: update_counts ();
153:
154: simple_unlock (&phys_lmm_lock);
155: splx (s);
156:
157: if (block)
158: return block;
159:
160: if (flags & OSENV_NONBLOCKING)
161: return 0;
162:
163: /* There is no space in the lmm. There may well be pages available on
164: the VM system's free list. If we're sure we are not being called
165: from an interrupt handler here, which we should be guaranteed by
166: checking for OSENV_NONBLOCKING, then we can just access the free
167: list directly here (vm_page_grab). Another approach is to just wake
168: up the pageout daemon to have it find some pages for the lmm and
169: then block until it wakes us up. lmm_wants_pages accumulates the
170: number of pages wanted by blocked threads like ourselves.
171: consider_lmm_collect will produce some memory, set lmm_want_pages to
172: zero, and wake up all blocked threads to retry their allocations. */
173: lmm_wants_pages += atop (round_page (size));
174: thread_wakeup_one ((event_t)&vm_page_queue_free_count);
175: assert_wait ((event_t)&lmm_wants_pages, FALSE);
176: thread_block (0);
177: /* The pageout daemon woke us up (see consider_lmm_collect)
178: after putting some memory back into the LMM for us.
179: XXX make sure we don't loop in livelock? */
180: }
181: }
182:
183:
184: void
185: free_for_oskit (void *block, osenv_memflags_t flags, oskit_size_t size)
186: {
187: if (flags & OSENV_AUTO_SIZE)
188: {
189: oskit_size_t *p = block;
190: size = *--p;
191: block = p;
192: }
193:
194: if (mach_osenv == 0)
195: /* This is early oskit startup code before the kernel is set up.
196: Always go directly to physical memory. */
197: flags |= OSENV_VIRT_EQ_PHYS|OSENV_PHYS_WIRED|OSENV_PHYS_CONTIG;
198:
199: #if 0
200: if (in_oskit_interrupt)
201: /* The oskit documentation says an interrupt caller must set the flag. */
202: assert (flags & OSENV_NONBLOCKING);
203: #endif /* ... but oskit/linux/shared/s_kmem.c doesn't. */
204:
205: if ((oskit_addr_t) block < phys_mem_max)
206: {
207: /* We got physical memory directly from the lmm. */
208: spl_t s;
209:
210: s = sploskit ();
211: simple_lock (&phys_lmm_lock);
212:
213: lmm_free (&malloc_lmm, block, size);
214: update_counts ();
215:
216: simple_unlock (&phys_lmm_lock);
217: splx (s);
218: }
219: else
220: {
221: if (in_oskit_interrupt)
222: {
223: /* This should be impossible if the caller (oskit) is consistent
224: in its use of OSENV_NONBLOCKING for allocations and
225: deallocations. alloc_for_oskit will always get physical
226: memory when called with the flag set. */
227: panic ("free_for_oskit of virtual memory from interrupt level");
228: /* If this ever happens, make a little free list and have the
229: pageout daemon run over it doing kfree. */
230: }
231: else
232: kfree ((vm_offset_t) block, size);
233: }
234: }
235:
236:
237: /*** Entry points from the VM system. ***/
238:
239:
240: /* Called only from vm_page_bootstrap, only for estimate. */
241: unsigned int pmap_free_pages()
242: {
243: return atop (lmm_avail (&malloc_lmm, 0));
244: }
245:
246:
247: /* This is called from pmap_bootstrap for kernel page table pages, and from
248: pmap_steal_memory for physical pages to back kernel virtual memory
249: allocated in early Mach startup. */
250: vm_offset_t
251: pmap_grab_page (void)
252: {
253: void *page = lmm_alloc_page (&malloc_lmm, 0);
254: if (page == 0)
255: panic ("Not enough memory to initialize Mach");
256: return (vm_offset_t) page;
257: }
258:
259: int
260: init_alloc (vm_size_t size, vm_offset_t *p)
261: {
262: void *block = lmm_alloc (&malloc_lmm, size, 0);
263: if (block == 0)
264: return 0;
265: *p = (vm_offset_t) block;
266: return 1;
267: }
268:
269:
270: /* in zalloc.c XXX */
271: extern vm_offset_t zdata;
272: extern vm_size_t zdata_size;
273:
274:
275: void pmap_startup(
276: vm_offset_t *startp,
277: vm_offset_t *endp)
278: {
279: unsigned int i, npages, initial_pages;
280: vm_page_t pages;
281:
282: /* Calculate how many pages can possibly go into the VM pool,
283: taking into account the space required for each page's own
284: vm_page_t structure. */
285: npages = ((lmm_avail (&malloc_lmm, 0) - round_page(zdata_size)) /
286: (PAGE_SIZE + sizeof *pages));
287:
288: /* We will allocate a quarter of the pages to start with.
289: That ought to be plenty enough to get the kernel up and running.
290: Once the pageout daemon has started, it will equalize the
291: free page queue and LMM free pool sizes. */
292: initial_pages = npages / 4;
293:
294: /* Steal some memory for the zone system, including enough
295: to cover the initial vm_page structures we will steal. */
296: zdata_size = (round_page (virtual_space_start + zdata_size +
297: initial_pages * sizeof *pages)
298: - virtual_space_start);
299: zdata = pmap_steal_memory (zdata_size);
300:
301: /* Steal vm_page structures from the zone system,
302: and physical pages from the LMM. */
303: pages = (void *) zdata;
304: for (i = 0; i < initial_pages; ++i)
305: {
306: vm_page_t mem = pages++;
307: void *page = lmm_alloc_page (&malloc_lmm, 0);
308: vm_page_init (mem, (vm_offset_t) page);
309: debug_protect_page (page);
310: vm_page_release (mem, FALSE);
311: }
312:
313: /* Account for the memory swiped for vm_page structures,
314: and return the rest of the stolen memory to the zone system. */
315: zdata_size = zdata + zdata_size - (vm_offset_t) pages;
316: zdata = (vm_offset_t) pages;
317:
318: /* Set the initial record of the number of pages available in the
319: LMM to a deliberate lie. This value will be used to set paging
320: algorithm parameters that should be based on what things look
321: like with all available physical pages in the VM pool. So here
322: we use the calculation that takes into account the overhead of
323: vm_page_t structures that we will have to consume to put pages
324: into the pool. Counting the free pages in the LMM will show
325: more pages available than we admit, since we haven't allocated
326: all of those structures up front. As soon as the pageout daemon
327: gets started up, it will recalculate from the LMM. */
328: vm_page_unqueued_count = npages - initial_pages;
329:
330:
331: /*
332: * We have to re-align virtual_space_start,
333: * because pmap_steal_memory has been using it.
334: */
335:
336: virtual_space_start = round_page(virtual_space_start);
337:
338: *startp = virtual_space_start;
339: *endp = virtual_space_end;
340: }
341:
342:
343: void
344: vm_page_grab_oskit_page (void)
345: {
346: void *page;
347: vm_page_t m;
348:
349: do
350: {
351: spl_t s = sploskit ();
352: simple_lock (&phys_lmm_lock);
353:
354: page = lmm_alloc_page (&malloc_lmm, 0);
355:
356: update_counts ();
357:
358: debug_protect_page (page);
359: simple_unlock (&phys_lmm_lock);
360: splx (s);
361:
362: if (page == 0)
363: panic (__FUNCTION__);
364:
365: m = (vm_page_t) zget(vm_page_zone);
366: if (m == VM_PAGE_NULL)
367: {
368: /* The zone is out of space. A normal zalloc would call
369: kmem_alloc_wired and wind up recursing down to here trying to
370: get a page. So instead we just stuff a physical page directly
371: into the zone, and loop for a new one to satisfy our caller. */
372: debug_unprotect_page (page);
373: zcram(vm_page_zone, (vm_offset_t) page, PAGE_SIZE);
374: }
375: } while (m == VM_PAGE_NULL);
376:
377: vm_page_init(m, (vm_offset_t) page);
378: vm_page_release(m, FALSE);
379: }
380:
381:
382: #define PAGE_BATCH 32
383:
384: /* Called by the pageout daemon to see if the vm_page_free_queue
385: and the LMM want to tango. */
386:
387: void
388: consider_lmm_collect (void)
389: {
390: spl_t s;
391: unsigned int need;
392:
393: /* First check if the LMM needs pages back for alloc_for_oskit calls. */
394: if (vm_page_unqueued_count < lmm_wants_pages
395: || vm_page_queue_free_count > 8 * vm_page_unqueued_count) /* random */
396: {
397: /* The LMM needs some physical pages back from the VM pool. */
398: need = lmm_wants_pages > PAGE_BATCH ? lmm_wants_pages : PAGE_BATCH;
399:
400: while (need > 0)
401: {
402: unsigned int batch = need > PAGE_BATCH ? PAGE_BATCH : need;
403: void *pages[PAGE_BATCH];
404: unsigned int i;
405:
406: for (i = 0; i < batch; ++i)
407: {
408: vm_page_t mem = vm_page_grab (FALSE);
409: if (mem == VM_PAGE_NULL)
410: break;
411: pages[i] = (void *) mem->phys_addr;
412: zfree (vm_page_zone, (vm_offset_t) mem);
413: debug_unprotect_page (pages[i]);
414: }
415:
416: s = sploskit ();
417: simple_lock (&phys_lmm_lock);
418:
419: while (i-- > 0)
420: lmm_free_page (&malloc_lmm, (void *) pages[i]);
421:
422: update_counts ();
423:
424: simple_unlock (&phys_lmm_lock);
425: splx (s);
426:
427: if (i < batch)
428: break;
429: need -= batch;
430: }
431: }
432:
433: /* If lmm_wants_pages is set, then some threads are blocked in
434: alloc_for_oskit. This might still be the case even if the memory was
435: released to the LMM before we ran so that we didn't do anything above.
436: We need to wake the blocked threads so they will all retry their
437: allocations. */
438: if (lmm_wants_pages != 0)
439: {
440: lmm_wants_pages = 0;
441: thread_wakeup ((event_t)&lmm_wants_pages);
442: }
443:
444: /* Any time the VM pool has fewer free pages than the LMM does,
445: we give it half the LMM's free pages. */
446:
447: if (vm_page_queue_free_count < vm_page_unqueued_count)
448: {
449: s = sploskit ();
450: simple_lock (&phys_lmm_lock);
451:
452: need = vm_page_unqueued_count / 2;
453:
454: /* We allocate only a single page at a time from the LMM, since we
455: don't need contiguous pages, and would rather use up fragmented
456: pages so as to leave the contiguous regions for those who need them.
457:
458: We must go to sploskit to call into the LMM, but back up to spl0 to
459: deliver the new pages to the VM system. We don't want to do this
460: for every single page allocation from the LMM, so we allocate
461: individual pages from the LMM in batches of PAGE_BATCH pages and
462: then reenable interrupts to deliver those pages before going back
463: for more. */
464:
465: while (need > 0)
466: {
467: unsigned int batch = need > PAGE_BATCH ? PAGE_BATCH : need;
468: void *pages[PAGE_BATCH];
469: unsigned int i;
470:
471: for (i = 0; i < batch; ++i)
472: {
473: /* This allocation should never fail, since we keep track
474: of the number of pages available in the lmm. */
475: pages[i] = lmm_alloc_page (&malloc_lmm, 0);
476: if (pages[i] == 0)
477: panic ("LMM unexpectedly out of physical pages");
478: debug_protect_page (pages[i]);
479: }
480:
481: update_counts ();
482:
483: simple_unlock (&phys_lmm_lock);
484: splx (s);
485:
486: while (i-- > 0)
487: vm_page_create ((vm_offset_t) pages[i],
488: (vm_offset_t) pages[i] + PAGE_SIZE);
489:
490: need -= batch;
491: if (need == 0)
492: break;
493:
494: s = sploskit ();
495: simple_lock (&phys_lmm_lock);
496: }
497: }
498: }
499:
500:
501: /*** oskit_osenv_mem_t COM object implementation ***/
502:
503:
504: /*
505: * There is one and only one memory interface in this implementation.
506: */
507: static struct oskit_osenv_mem_ops osenv_mem_ops;
508: static struct oskit_osenv_mem osenv_mem_object = {&osenv_mem_ops};
509:
510: static OSKIT_COMDECL
511: mem_query(oskit_osenv_mem_t *s, const oskit_iid_t *iid, void **out_ihandle)
512: {
513: if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
514: memcmp(iid, &oskit_osenv_mem_iid, sizeof(*iid)) == 0) {
515: *out_ihandle = s;
516: return 0;
517: }
518:
519: *out_ihandle = 0;
520: return OSKIT_E_NOINTERFACE;
521: };
522:
523: static OSKIT_COMDECL_U
524: mem_addref(oskit_osenv_mem_t *s)
525: {
526: /* Only one object */
527: return 1;
528: }
529:
530: static OSKIT_COMDECL_U
531: mem_release(oskit_osenv_mem_t *s)
532: {
533: /* Only one object */
534: return 1;
535: }
536:
537: static void * OSKIT_COMCALL
538: mem_alloc(oskit_osenv_mem_t *o, oskit_size_t size,
539: osenv_memflags_t flags, unsigned align)
540: {
541: return alloc_for_oskit (size, flags, align);
542: }
543:
544: static OSKIT_COMDECL_V
545: mem_free(oskit_osenv_mem_t *o, void *block,
546: osenv_memflags_t flags, oskit_size_t size)
547: {
548: free_for_oskit (block, flags, size);
549: }
550:
551: static oskit_addr_t OSKIT_COMCALL
552: mem_getphys(oskit_osenv_mem_t *o, oskit_addr_t va)
553: {
554: /* We can only use kvtophys for memory allocated with OSENV_PHYS_CONTIG.
555: But at least some code (e.g. eepro100 driver) will call us with an
556: address on a kernel stack and expect to get a physical address from that.
557: Checking the kernel pmap is a little heavy but should be correct in
558: all cases. */
559: return pmap_extract (kernel_pmap, va);
560: }
561:
562: static oskit_addr_t OSKIT_COMCALL
563: mem_getvirt(oskit_osenv_mem_t *o, oskit_addr_t pa)
564: {
565: return ((oskit_addr_t)phystokv(pa));
566: }
567:
568: static oskit_addr_t OSKIT_COMCALL
569: mem_physmax(oskit_osenv_mem_t *o)
570: {
571: return phys_mem_max;
572: }
573:
574: static OSKIT_COMDECL_U
575: mem_mapphys(oskit_osenv_mem_t *o, oskit_addr_t pa,
576: oskit_size_t size, void **addr, int flags)
577: {
578: kern_return_t kr;
579: vm_offset_t kva;
580:
581: if (trunc_page (pa) != 0 &&
582: trunc_page (pa) >= trunc_page (phys_mem_min) &&
583: round_page (pa + size) < round_page (phys_mem_max))
584: {
585: /* Direct mapping already covers it. */
586: *addr = (void *) phystokv (pa);
587: return 0;
588: }
589:
590: kr = kmem_alloc_pageable (kernel_map, &kva, round_page (size));
591: if (kr)
592: return OSKIT_E_OUTOFMEMORY;
593:
594: pmap_map (kva, trunc_page (pa), round_page (pa + size),
595: VM_PROT_READ | VM_PROT_WRITE);
596:
597: *addr = (char *) kva + (pa & PAGE_MASK);
598: return 0;
599: }
600:
601: #if NCPUS > 1
602: /* This function is used as a callback from smp_init_paging. */
603: oskit_addr_t
604: smp_map_range (oskit_addr_t start, oskit_size_t size)
605: {
606: oskit_error_t err = mem_mapphys (0, start, size, (void **)&start, 0);
607: return err ? 0 : start;
608: }
609: #endif
610:
611:
612: static struct oskit_osenv_mem_ops osenv_mem_ops = {
613: mem_query,
614: mem_addref,
615: mem_release,
616: mem_alloc,
617: mem_free,
618: mem_getphys,
619: mem_getvirt,
620: mem_physmax,
621: mem_mapphys,
622: };
623:
624: /*
625: * Return a reference to the one and only memory interface object.
626: */
627: oskit_osenv_mem_t *
628: oskit_create_osenv_mem(void)
629: {
630: return &osenv_mem_object;
631: }
632:
633:
634: /*** oskit_mem_t COM object implementation ***/
635:
636:
637: /* the COM object */
638: static struct oskit_mem_ops mem_ops;
639: static oskit_mem_t oskit_mem = { &mem_ops };
640:
641:
642: static OSKIT_COMDECL
643: mem2_query(oskit_mem_t *m, const oskit_iid_t *iid, void **out_ihandle)
644: {
645: if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
646: memcmp(iid, &oskit_mem_iid, sizeof(*iid)) == 0) {
647: *out_ihandle = m;
648: return 0;
649: }
650:
651: *out_ihandle = 0;
652: return OSKIT_E_NOINTERFACE;
653: };
654:
655: static OSKIT_COMDECL_U
656: mem2_addref(oskit_mem_t *m)
657: {
658: /* No reference counting; only one of them */
659: return 1;
660: }
661:
662: static OSKIT_COMDECL_U
663: mem2_release(oskit_mem_t *m)
664: {
665: /* No reference counting; only one of them */
666: return 1;
667: }
668:
669: static void * OSKIT_COMCALL
670: mem2_alloc(oskit_mem_t *m, oskit_u32_t size, oskit_u32_t flags)
671: {
672: return alloc_for_oskit (size, flags, 0);
673: }
674:
675: static void * OSKIT_COMCALL
676: mem2_realloc(oskit_mem_t *m, void *ptr,
677: oskit_u32_t oldsize, oskit_u32_t newsize, oskit_u32_t flags)
678: {
679: if (flags & OSKIT_MEM_AUTO_SIZE)
680: {
681: oskit_size_t *op = ptr, *new;
682: oldsize = *--op;
683: newsize += sizeof (oskit_size_t);
684: new = alloc_for_oskit (newsize, flags, 0);
685: if (new)
686: {
687: *new++ = newsize;
688: memcpy (new, ptr, oldsize - sizeof (oskit_size_t));
689: free_for_oskit (op, flags, oldsize);
690: }
691: return new;
692: }
693: else
694: {
695: void *new = alloc_for_oskit (newsize, flags, 0);
696: if (new)
697: {
698: memcpy (new, ptr, oldsize);
699: free_for_oskit (ptr, flags, oldsize);
700: }
701: return new;
702: }
703: }
704:
705: static void *OSKIT_COMCALL
706: mem2_alloc_aligned(oskit_mem_t *m,
707: oskit_u32_t size, oskit_u32_t flags, oskit_u32_t align)
708: {
709: return alloc_for_oskit (size, flags, align);
710: }
711:
712: static void OSKIT_COMCALL
713: mem2_free(oskit_mem_t *m, void *ptr, oskit_u32_t size, oskit_u32_t flags)
714: {
715: if (ptr)
716: free_for_oskit (ptr, flags, size);
717: }
718:
719: static oskit_u32_t OSKIT_COMCALL
720: mem2_getsize(oskit_mem_t *m, void *ptr)
721: {
722: if (ptr) {
723: oskit_u32_t *chunk = (oskit_u32_t *)ptr - 1;
724:
725: return *chunk;
726: }
727: return 0;
728: }
729:
730: static void *OSKIT_COMCALL
731: mem2_alloc_gen(oskit_mem_t *m,
732: oskit_u32_t size, oskit_u32_t flags,
733: oskit_u32_t align_bits, oskit_u32_t align_ofs)
734: {
735: if (align_ofs != 0)
736: panic ("alloc with align_bits=%u align_ofs=%u",
737: align_bits, align_ofs);
738: return alloc_for_oskit (size, flags, 1 << align_bits);
739: }
740:
741: static oskit_size_t OSKIT_COMCALL
742: mem2_avail(oskit_mem_t *m, oskit_u32_t flags)
743: {
744: panic ("mem_avail");
745: }
746:
747: static OSKIT_COMDECL_V
748: mem2_dump(oskit_mem_t *m)
749: {
750: panic ("mem_dump");
751: }
752:
753: static struct oskit_mem_ops mem_ops = {
754: mem2_query,
755: mem2_addref,
756: mem2_release,
757: mem2_alloc,
758: mem2_realloc,
759: mem2_alloc_aligned,
760: mem2_free,
761: mem2_getsize,
762: mem2_alloc_gen,
763: mem2_avail,
764: mem2_dump,
765: };
766:
767: /*
768: * Not a lot to do in this impl.
769: */
770: oskit_mem_t *
771: oskit_mem_init(void)
772: {
773: return &oskit_mem;
774: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.