32fbbd370c
shared with the kernel, mapped into kernel address space; kernel is notified of its location. kernel segment size is increased to make it fit. - map in kernel and other processes that don't have their own page table using single 4MB (global) mapping. - new sanity check facility: objects that are allocated with the slab allocator are, when running with sanity checking on, marked readonly until they are explicitly unlocked using the USE() macro. - another sanity check facility: collect all uses of memory and see if they don't overlap with (a) eachother and (b) free memory - own munmap() and munmap_text() functions. - exec() recovers from out-of-memory conditions properly now; this solves some weird exec() behaviour - chew off memory from the same side of the chunk as where we start scanning, solving some memory fragmentation issues - use avl trees for freelist and phys_ranges in regions - implement most useful part of munmap() - remap() stuff is GQ's for shared memory
141 lines
3.9 KiB
C
141 lines
3.9 KiB
C
|
|
#define _SYSTEM 1
|
|
|
|
#define VERBOSE 0
|
|
|
|
#include <minix/callnr.h>
|
|
#include <minix/com.h>
|
|
#include <minix/config.h>
|
|
#include <minix/const.h>
|
|
#include <minix/ds.h>
|
|
#include <minix/endpoint.h>
|
|
#include <minix/keymap.h>
|
|
#include <minix/minlib.h>
|
|
#include <minix/type.h>
|
|
#include <minix/ipc.h>
|
|
#include <minix/sysutil.h>
|
|
#include <minix/syslib.h>
|
|
#include <minix/safecopies.h>
|
|
#include <minix/bitmap.h>
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <env.h>
|
|
#include <stdio.h>
|
|
|
|
#include "glo.h"
|
|
#include "proto.h"
|
|
#include "util.h"
|
|
|
|
/*===========================================================================*
|
|
* register_callback *
|
|
*===========================================================================*/
|
|
PRIVATE void register_callback(struct vmproc *for_who, callback_t callback,
|
|
int callback_type)
|
|
{
|
|
if(for_who->vm_callback) {
|
|
vm_panic("register_callback: callback already registered",
|
|
for_who->vm_callback_type);
|
|
}
|
|
for_who->vm_callback = callback;
|
|
for_who->vm_callback_type = callback_type;
|
|
|
|
return;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* vfs_open *
|
|
*===========================================================================*/
|
|
PUBLIC int vfs_open(struct vmproc *for_who, callback_t callback,
|
|
cp_grant_id_t filename_gid, int filename_len, int flags, int mode)
|
|
{
|
|
static message m;
|
|
int r;
|
|
|
|
register_callback(for_who, callback, VM_VFS_REPLY_OPEN);
|
|
|
|
m.m_type = VM_VFS_OPEN;
|
|
m.VMVO_NAME_GRANT = filename_gid;
|
|
m.VMVO_NAME_LENGTH = filename_len;
|
|
m.VMVO_FLAGS = flags;
|
|
m.VMVO_MODE = mode;
|
|
m.VMVO_ENDPOINT = for_who->vm_endpoint;
|
|
|
|
if((r=asynsend(VFS_PROC_NR, &m)) != OK) {
|
|
vm_panic("vfs_open: asynsend failed", r);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* vfs_close *
|
|
*===========================================================================*/
|
|
PUBLIC int vfs_close(struct vmproc *for_who, callback_t callback, int fd)
|
|
{
|
|
static message m;
|
|
int r;
|
|
|
|
register_callback(for_who, callback, VM_VFS_REPLY_CLOSE);
|
|
|
|
m.m_type = VM_VFS_CLOSE;
|
|
m.VMVC_ENDPOINT = for_who->vm_endpoint;
|
|
m.VMVC_FD = fd;
|
|
|
|
if((r=asynsend(VFS_PROC_NR, &m)) != OK) {
|
|
vm_panic("vfs_close: asynsend failed", r);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* do_vfs_reply *
|
|
*===========================================================================*/
|
|
PUBLIC int do_vfs_reply(message *m)
|
|
{
|
|
/* Reply to a request has been received from vfs. Handle it. First verify
|
|
* and look up which process, identified by endpoint, this is about.
|
|
* Then call the callback function that was registered when the request
|
|
* was done. Return result to vfs.
|
|
*/
|
|
endpoint_t ep;
|
|
struct vmproc *vmp;
|
|
int procno;
|
|
callback_t cb;
|
|
ep = m->VMV_ENDPOINT;
|
|
if(vm_isokendpt(ep, &procno) != OK) {
|
|
printf("VM:do_vfs_reply: reply %d about invalid endpoint %d\n",
|
|
m->m_type, ep);
|
|
vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
|
|
}
|
|
vmp = &vmproc[procno];
|
|
if(!vmp->vm_callback) {
|
|
printf("VM:do_vfs_reply: reply %d: endpoint %d not waiting\n",
|
|
m->m_type, ep);
|
|
vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
|
|
}
|
|
if(vmp->vm_callback_type != m->m_type) {
|
|
printf("VM:do_vfs_reply: reply %d unexpected for endpoint %d\n"
|
|
" (expecting %d)\n", m->m_type, ep, vmp->vm_callback_type);
|
|
vm_panic("do_vfs_reply: invalid reply from vfs", NO_NUM);
|
|
}
|
|
if(vmp->vm_flags & VMF_EXITING) {
|
|
/* This is not fatal or impossible, but the callback
|
|
* function has to realize it shouldn't do any PM or
|
|
* VFS calls for this process.
|
|
*/
|
|
printf("VM:do_vfs_reply: reply %d for EXITING endpoint %d\n",
|
|
m->m_type, ep);
|
|
}
|
|
|
|
/* All desired callback state has been used, so save and reset
|
|
* the callback. This allows the callback to register another
|
|
* one.
|
|
*/
|
|
cb = vmp->vm_callback;
|
|
vmp->vm_callback = NULL;
|
|
cb(vmp, m);
|
|
return SUSPEND;
|
|
}
|
|
|