mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Mixed changes
- Added automatic utcb map/prefaulting of forked tasks for fs0 so that it does not need to explicitly request those tasks from mm0. Eliminating fs0 requests to mm0 reduce deadlock possibilities. - Replaced kmalloc with a public malloc implementation because of a bug in kmalloc. - Fixed a kfree bug. default_release_pages was trying to free page_array pages.
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
#include INC_SUBARCH(mm.h)
|
||||
|
||||
/* Abort debugging conditions */
|
||||
#define DEBUG_ABORTS
|
||||
// #define DEBUG_ABORTS
|
||||
#if defined (DEBUG_ABORTS)
|
||||
#define dbg_abort(...) dprintk(__VA_ARGS__)
|
||||
#else
|
||||
|
||||
@@ -30,7 +30,7 @@ int pager_sys_open(l4id_t sender, int fd, unsigned long vnum, unsigned long size
|
||||
{
|
||||
int err;
|
||||
|
||||
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
|
||||
printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
|
||||
|
||||
l4_save_ipcregs();
|
||||
|
||||
|
||||
@@ -88,6 +88,38 @@ struct tcb *create_tcb(void)
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches to task's utcb. FIXME: Add SHM_RDONLY and test it.
|
||||
* FIXME: This calls the pager and is a potential for deadlock
|
||||
*/
|
||||
int task_utcb_attach(struct tcb *t)
|
||||
{
|
||||
int shmid;
|
||||
void *shmaddr;
|
||||
|
||||
/* Use it as a key to create a shared memory region */
|
||||
if ((shmid = shmget((key_t)t->utcb_address, PAGE_SIZE, 0)) == -1)
|
||||
goto out_err;
|
||||
|
||||
/* Attach to the region */
|
||||
if ((int)(shmaddr = shmat(shmid, (void *)t->utcb_address, 0)) == -1)
|
||||
goto out_err;
|
||||
|
||||
/* Ensure address is right */
|
||||
if ((unsigned long)shmaddr != t->utcb_address)
|
||||
return -EINVAL;
|
||||
|
||||
// printf("%s: Mapped utcb of task %d @ 0x%x\n",
|
||||
// __TASKNAME__, t->tid, shmaddr);
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
printf("%s: Mapping utcb of task %d failed with err: %d.\n",
|
||||
__TASKNAME__, t->tid, errno);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receives ipc from pager about a new fork event and
|
||||
* the information on the resulting child task.
|
||||
@@ -121,6 +153,7 @@ int pager_notify_fork(l4id_t sender, l4id_t parid,
|
||||
memcpy(child->fd, parent->fd, TASK_FILES_MAX * sizeof(int));
|
||||
|
||||
l4_ipc_return(0);
|
||||
|
||||
printf("%s/%s: Exiting...\n", __TASKNAME__, __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
@@ -152,35 +185,6 @@ struct task_data_head *receive_pager_taskdata(void)
|
||||
return (struct task_data_head *)utcb_page;
|
||||
}
|
||||
|
||||
/* Attaches to task's utcb. FIXME: Add SHM_RDONLY and test it. */
|
||||
int task_utcb_attach(struct tcb *t)
|
||||
{
|
||||
int shmid;
|
||||
void *shmaddr;
|
||||
|
||||
/* Use it as a key to create a shared memory region */
|
||||
if ((shmid = shmget((key_t)t->utcb_address, PAGE_SIZE, 0)) == -1)
|
||||
goto out_err;
|
||||
|
||||
/* Attach to the region */
|
||||
if ((int)(shmaddr = shmat(shmid, (void *)t->utcb_address, 0)) == -1)
|
||||
goto out_err;
|
||||
|
||||
/* Ensure address is right */
|
||||
if ((unsigned long)shmaddr != t->utcb_address)
|
||||
return -EINVAL;
|
||||
|
||||
// printf("%s: Mapped utcb of task %d @ 0x%x\n",
|
||||
// __TASKNAME__, t->tid, shmaddr);
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
printf("%s: Mapping utcb of task %d failed with err: %d.\n",
|
||||
__TASKNAME__, t->tid, errno);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int init_task_structs(struct task_data_head *tdata_head)
|
||||
{
|
||||
|
||||
@@ -23,9 +23,9 @@ extern struct list_head km_area_start;
|
||||
void kmalloc_init(void);
|
||||
|
||||
/* Kmalloc allocation functions */
|
||||
void *kmalloc(int size);
|
||||
void *kzalloc(int size);
|
||||
int kfree(void *vaddr);
|
||||
void *kmalloc(int size) __attribute__((weak));
|
||||
void *kzalloc(int size) __attribute__((weak));
|
||||
int kfree(void *vaddr) __attribute__((weak));
|
||||
|
||||
#endif /* __KMALLOC_H__ */
|
||||
|
||||
|
||||
19
tasks/mm0/include/lib/malloc.h
Normal file
19
tasks/mm0/include/lib/malloc.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef __PRIVATE_MALLOC_H__
|
||||
#define __PRIVATE_MALLOC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
void *kmalloc(size_t size);
|
||||
void kfree(void *blk);
|
||||
|
||||
static inline void *kzalloc(size_t size)
|
||||
{
|
||||
void *buf = kmalloc(size);
|
||||
|
||||
memset(buf, 0, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
#endif /*__PRIVATE_MALLOC_H__ */
|
||||
@@ -43,7 +43,7 @@ struct shm_descriptor {
|
||||
/* Initialises shared memory bookkeeping structures */
|
||||
void shm_init();
|
||||
|
||||
void *shmat_shmget_internal(key_t key, void *shmaddr);
|
||||
void *shmat_shmget_internal(struct tcb *task, key_t key, void *shmaddr);
|
||||
struct vm_file *shm_new(key_t key, unsigned long npages);
|
||||
|
||||
#endif /* __SHM_H__ */
|
||||
|
||||
@@ -101,5 +101,6 @@ void init_pm(struct initdata *initdata);
|
||||
|
||||
struct tcb *task_create(struct task_ids *ids, unsigned int flags);
|
||||
int send_task_data(l4id_t requester);
|
||||
void task_map_prefault_utcb(struct tcb *mapper, struct tcb *owner);
|
||||
|
||||
#endif /* __TASK_H__ */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <arch/mm.h>
|
||||
#include <lib/spinlock.h>
|
||||
|
||||
#define DEBUG_FAULT_HANDLING
|
||||
// #define DEBUG_FAULT_HANDLING
|
||||
#ifdef DEBUG_FAULT_HANDLING
|
||||
#define dprintf(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
|
||||
@@ -120,6 +120,7 @@ int vfs_notify_fork(struct tcb *child, struct tcb *parent)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int do_fork(struct tcb *parent)
|
||||
{
|
||||
struct tcb *child;
|
||||
@@ -155,7 +156,13 @@ int do_fork(struct tcb *parent)
|
||||
}
|
||||
/* FIXME: We should munmap() parent's utcb page from child */
|
||||
|
||||
/* Notify fs0 about forked process */
|
||||
/*
|
||||
* Map and prefault child utcb to vfs so that vfs need not
|
||||
* call us with such requests
|
||||
*/
|
||||
task_map_prefault_utcb(find_task(VFS_TID), child);
|
||||
|
||||
/* We can now notify vfs about forked process */
|
||||
vfs_notify_fork(child, parent);
|
||||
|
||||
/* Add child to global task list */
|
||||
|
||||
418
tasks/mm0/src/lib/malloc.c
Normal file
418
tasks/mm0/src/lib/malloc.c
Normal file
@@ -0,0 +1,418 @@
|
||||
/*****************************************************************************
|
||||
Simple malloc
|
||||
Chris Giese <geezer@execpc.com> http://www.execpc.com/~geezer
|
||||
Release date: Oct 30, 2002
|
||||
This code is public domain (no copyright).
|
||||
You can do whatever you want with it.
|
||||
|
||||
Features:
|
||||
- First-fit
|
||||
- free() coalesces adjacent free blocks
|
||||
- Uses variable-sized heap, enlarged with kbrk()/sbrk() function
|
||||
- Does not use mmap()
|
||||
- Can be easily modified to use fixed-size heap
|
||||
- Works with 16- or 32-bit compilers
|
||||
|
||||
Build this program with either of the two main() functions, then run it.
|
||||
Messages that indicate a software error will contain three asterisks (***).
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy(), memset() */
|
||||
#include <stdio.h> /* printf() */
|
||||
#include <l4/macros.h>
|
||||
#define _32BIT 1
|
||||
|
||||
/* use small (32K) heap for 16-bit compilers,
|
||||
large (500K) heap for 32-bit compilers */
|
||||
#if defined(_32BIT)
|
||||
#define HEAP_SIZE 500000uL
|
||||
#else
|
||||
#define HEAP_SIZE 32768u
|
||||
#endif
|
||||
|
||||
#define MALLOC_MAGIC 0x6D92 /* must be < 0x8000 */
|
||||
|
||||
typedef struct _malloc /* Turbo C DJGPP */
|
||||
{
|
||||
size_t size; /* 2 bytes 4 bytes */
|
||||
struct _malloc *next; /* 2 bytes 4 bytes */
|
||||
unsigned magic : 15; /* 2 bytes total 4 bytes total */
|
||||
unsigned used : 1;
|
||||
} malloc_t; /* total 6 bytes 12 bytes */
|
||||
|
||||
static char *g_heap_bot, *g_kbrk, *g_heap_top;
|
||||
/*****************************************************************************
|
||||
*****************************************************************************/
|
||||
void dump_heap(void)
|
||||
{
|
||||
unsigned blks_used = 0, blks_free = 0;
|
||||
size_t bytes_used = 0, bytes_free = 0;
|
||||
malloc_t *m;
|
||||
int total;
|
||||
|
||||
printf("===============================================\n");
|
||||
for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
|
||||
{
|
||||
printf("blk %5p: %6u bytes %s\n", m,
|
||||
m->size, m->used ? "used" : "free");
|
||||
if(m->used)
|
||||
{
|
||||
blks_used++;
|
||||
bytes_used += m->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
blks_free++;
|
||||
bytes_free += m->size;
|
||||
}
|
||||
}
|
||||
printf("blks: %6u used, %6u free, %6u total\n", blks_used,
|
||||
blks_free, blks_used + blks_free);
|
||||
printf("bytes: %6u used, %6u free, %6u total\n", bytes_used,
|
||||
bytes_free, bytes_used + bytes_free);
|
||||
printf("g_heap_bot=0x%p, g_kbrk=0x%p, g_heap_top=0x%p\n",
|
||||
g_heap_bot, g_kbrk, g_heap_top);
|
||||
total = (bytes_used + bytes_free) +
|
||||
(blks_used + blks_free) * sizeof(malloc_t);
|
||||
if(total != g_kbrk - g_heap_bot)
|
||||
printf("*** some heap memory is not accounted for\n");
|
||||
printf("===============================================\n");
|
||||
}
|
||||
/*****************************************************************************
|
||||
POSIX sbrk() looks like this
|
||||
void *sbrk(int incr);
|
||||
Mine is a bit different so I can signal the calling function
|
||||
if more memory than desired was allocated (e.g. in a system with paging)
|
||||
If your kbrk()/sbrk() always allocates the amount of memory you ask for,
|
||||
this code can be easily changed.
|
||||
|
||||
int brk( void *sbrk( void *kbrk(
|
||||
function void *adr); int delta); int *delta);
|
||||
---------------------- ------------ ------------ -------------
|
||||
POSIX? yes yes NO
|
||||
return value if error -1 -1 NULL
|
||||
get break value . sbrk(0) int x=0; kbrk(&x);
|
||||
set break value to X brk(X) sbrk(X - sbrk(0)) int x=X, y=0; kbrk(&x) - kbrk(&y);
|
||||
enlarge heap by N bytes . sbrk(+N) int x=N; kbrk(&x);
|
||||
shrink heap by N bytes . sbrk(-N) int x=-N; kbrk(&x);
|
||||
can you tell if you're
|
||||
given more memory
|
||||
than you wanted? no no yes
|
||||
*****************************************************************************/
|
||||
static void *kbrk(int *delta)
|
||||
{
|
||||
static char heap[HEAP_SIZE];
|
||||
/**/
|
||||
char *new_brk, *old_brk;
|
||||
|
||||
/* heap doesn't exist yet */
|
||||
if(g_heap_bot == NULL)
|
||||
{
|
||||
g_heap_bot = g_kbrk = heap;
|
||||
g_heap_top = g_heap_bot + HEAP_SIZE;
|
||||
}
|
||||
new_brk = g_kbrk + (*delta);
|
||||
/* too low: return NULL */
|
||||
if(new_brk < g_heap_bot)
|
||||
return NULL;
|
||||
/* too high: return NULL */
|
||||
if(new_brk >= g_heap_top)
|
||||
return NULL;
|
||||
/* success: adjust brk value... */
|
||||
old_brk = g_kbrk;
|
||||
g_kbrk = new_brk;
|
||||
/* ...return actual delta... (for this sbrk(), they are the same)
|
||||
(*delta) = (*delta); */
|
||||
/* ...return old brk value */
|
||||
return old_brk;
|
||||
}
|
||||
/*****************************************************************************
|
||||
kmalloc() and kfree() use g_heap_bot, but not g_kbrk nor g_heap_top
|
||||
*****************************************************************************/
|
||||
void *kmalloc(size_t size)
|
||||
{
|
||||
unsigned total_size;
|
||||
malloc_t *m, *n;
|
||||
int delta;
|
||||
|
||||
if(size == 0)
|
||||
return NULL;
|
||||
total_size = size + sizeof(malloc_t);
|
||||
/* search heap for free block (FIRST FIT) */
|
||||
m = (malloc_t *)g_heap_bot;
|
||||
/* g_heap_bot == 0 == NULL if heap does not yet exist */
|
||||
if(m != NULL)
|
||||
{
|
||||
if(m->magic != MALLOC_MAGIC)
|
||||
// panic("kernel heap is corrupt in kmalloc()");
|
||||
{
|
||||
printf("*** kernel heap is corrupt in kmalloc()\n");
|
||||
return NULL;
|
||||
}
|
||||
for(; m->next != NULL; m = m->next)
|
||||
{
|
||||
if(m->used)
|
||||
continue;
|
||||
/* size == m->size is a perfect fit */
|
||||
if(size == m->size)
|
||||
m->used = 1;
|
||||
else
|
||||
{
|
||||
/* otherwise, we need an extra sizeof(malloc_t) bytes for the header
|
||||
of a second, free block */
|
||||
if(total_size > m->size)
|
||||
continue;
|
||||
/* create a new, smaller free block after this one */
|
||||
n = (malloc_t *)((char *)m + total_size);
|
||||
n->size = m->size - total_size;
|
||||
n->next = m->next;
|
||||
n->magic = MALLOC_MAGIC;
|
||||
n->used = 0;
|
||||
/* reduce the size of this block and mark it used */
|
||||
m->size = size;
|
||||
m->next = n;
|
||||
m->used = 1;
|
||||
}
|
||||
return (char *)m + sizeof(malloc_t);
|
||||
}
|
||||
}
|
||||
/* use kbrk() to enlarge (or create!) heap */
|
||||
delta = total_size;
|
||||
n = kbrk(&delta);
|
||||
/* uh-oh */
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
if(m != NULL)
|
||||
m->next = n;
|
||||
n->size = size;
|
||||
n->magic = MALLOC_MAGIC;
|
||||
n->used = 1;
|
||||
/* did kbrk() return the exact amount of memory we wanted?
|
||||
cast to make "gcc -Wall -W ..." shut the hell up */
|
||||
if((int)total_size == delta)
|
||||
n->next = NULL;
|
||||
else
|
||||
{
|
||||
/* it returned more than we wanted (it will never return less):
|
||||
create a new, free block */
|
||||
m = (malloc_t *)((char *)n + total_size);
|
||||
m->size = delta - total_size - sizeof(malloc_t);
|
||||
m->next = NULL;
|
||||
m->magic = MALLOC_MAGIC;
|
||||
m->used = 0;
|
||||
|
||||
n->next = m;
|
||||
}
|
||||
return (char *)n + sizeof(malloc_t);
|
||||
}
|
||||
|
||||
static inline void *kzalloc(size_t size)
|
||||
{
|
||||
void *buf = kmalloc(size);
|
||||
|
||||
memset(buf, 0, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*****************************************************************************/
|
||||
void kfree(void *blk)
|
||||
{
|
||||
malloc_t *m, *n;
|
||||
|
||||
/* get address of header */
|
||||
m = (malloc_t *)((char *)blk - sizeof(malloc_t));
|
||||
if(m->magic != MALLOC_MAGIC)
|
||||
// panic("attempt to kfree() block at 0x%p "
|
||||
// "with bad magic value", blk);
|
||||
{
|
||||
printf("*** attempt to kfree() block at 0x%p "
|
||||
"with bad magic value\n", blk);
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
/* find this block in the heap */
|
||||
n = (malloc_t *)g_heap_bot;
|
||||
if(n->magic != MALLOC_MAGIC)
|
||||
// panic("kernel heap is corrupt in kfree()");
|
||||
{
|
||||
printf("*** kernel heap is corrupt in kfree()\n");
|
||||
return;
|
||||
}
|
||||
for(; n != NULL; n = n->next)
|
||||
{
|
||||
if(n == m)
|
||||
break;
|
||||
}
|
||||
/* not found? bad pointer or no heap or something else? */
|
||||
if(n == NULL)
|
||||
// panic("attempt to kfree() block at 0x%p "
|
||||
// "that is not in the heap", blk);
|
||||
{
|
||||
printf("*** attempt to kfree() block at 0x%p "
|
||||
"that is not in the heap\n", blk);
|
||||
return;
|
||||
}
|
||||
/* free the block */
|
||||
m->used = 0;
|
||||
/* coalesce adjacent free blocks
|
||||
Hard to spell, hard to do */
|
||||
for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
|
||||
{
|
||||
while(!m->used && m->next != NULL && !m->next->used)
|
||||
{
|
||||
/* resize this block */
|
||||
m->size += sizeof(malloc_t) + m->next->size;
|
||||
/* merge with next block */
|
||||
m->next = m->next->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
*****************************************************************************/
|
||||
void *krealloc(void *blk, size_t size)
|
||||
{
|
||||
void *new_blk;
|
||||
malloc_t *m;
|
||||
|
||||
/* size == 0: free block */
|
||||
if(size == 0)
|
||||
{
|
||||
if(blk != NULL)
|
||||
kfree(blk);
|
||||
new_blk = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allocate new block */
|
||||
new_blk = kmalloc(size);
|
||||
/* if allocation OK, and if old block exists, copy old block to new */
|
||||
if(new_blk != NULL && blk != NULL)
|
||||
{
|
||||
m = (malloc_t *)((char *)blk - sizeof(malloc_t));
|
||||
if(m->magic != MALLOC_MAGIC)
|
||||
// panic("attempt to krealloc() block at "
|
||||
// "0x%p with bad magic value", blk);
|
||||
{
|
||||
printf("*** attempt to krealloc() block at "
|
||||
"0x%p with bad magic value\n", blk);
|
||||
return NULL;
|
||||
}
|
||||
/* copy minimum of old and new block sizes */
|
||||
if(size > m->size)
|
||||
size = m->size;
|
||||
memcpy(new_blk, blk, size);
|
||||
/* free the old block */
|
||||
kfree(blk);
|
||||
}
|
||||
}
|
||||
return new_blk;
|
||||
}
|
||||
/*****************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
#include <stdlib.h> /* rand() */
|
||||
|
||||
|
||||
#define SLOTS 17
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned lifetime[SLOTS];
|
||||
void *blk[SLOTS];
|
||||
int i, j, k;
|
||||
|
||||
dump_heap();
|
||||
memset(lifetime, 0, sizeof(lifetime));
|
||||
memset(blk, 0, sizeof(blk));
|
||||
for(i = 0; i < 1000; i++)
|
||||
{
|
||||
printf("Pass %6u\n", i);
|
||||
for(j = 0; j < SLOTS; j++)
|
||||
{
|
||||
/* age the block */
|
||||
if(lifetime[j] != 0)
|
||||
{
|
||||
(lifetime[j])--;
|
||||
continue;
|
||||
}
|
||||
/* too old; free it */
|
||||
if(blk[j] != NULL)
|
||||
{
|
||||
kfree(blk[j]);
|
||||
blk[j] = NULL;
|
||||
}
|
||||
/* alloc new block of random size
|
||||
Note that size_t==unsigned, but kmalloc() uses integer math,
|
||||
so block size must be positive integer */
|
||||
#if defined(_32BIT)
|
||||
k = rand() % 40960 + 1;
|
||||
#else
|
||||
k = rand() % 4096 + 1;
|
||||
#endif
|
||||
blk[j] = kmalloc(k);
|
||||
if(blk[j] == NULL)
|
||||
printf("failed to alloc %u bytes\n", k);
|
||||
else
|
||||
/* give it a random lifetime 0-20 */
|
||||
lifetime[j] = rand() % 21;
|
||||
}
|
||||
}
|
||||
/* let's see what we've wrought */
|
||||
printf("\n\n");
|
||||
dump_heap();
|
||||
/* free everything */
|
||||
for(j = 0; j < SLOTS; j++)
|
||||
{
|
||||
if(blk[j] != NULL)
|
||||
{
|
||||
kfree(blk[j]);
|
||||
blk[j] = NULL;
|
||||
}
|
||||
(lifetime[j]) = 0;
|
||||
}
|
||||
/* after all that, we should have a single, unused block */
|
||||
dump_heap();
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *b1, *b2, *b3;
|
||||
|
||||
dump_heap();
|
||||
|
||||
b1 = kmalloc(42);
|
||||
dump_heap();
|
||||
|
||||
b2 = kmalloc(23);
|
||||
dump_heap();
|
||||
|
||||
b3 = kmalloc(7);
|
||||
dump_heap();
|
||||
|
||||
b2 = krealloc(b2, 24);
|
||||
dump_heap();
|
||||
|
||||
kfree(b1);
|
||||
dump_heap();
|
||||
|
||||
b1 = kmalloc(5);
|
||||
dump_heap();
|
||||
|
||||
kfree(b2);
|
||||
dump_heap();
|
||||
|
||||
kfree(b3);
|
||||
dump_heap();
|
||||
|
||||
kfree(b1);
|
||||
dump_heap();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -52,8 +52,11 @@ int default_release_pages(struct vm_object *vm_obj)
|
||||
/* Return page back to allocator */
|
||||
free_page((void *)page_to_phys(p));
|
||||
|
||||
/* Free the page structure */
|
||||
kfree(p);
|
||||
/*
|
||||
* Reset the page structure.
|
||||
* No freeing for page_array pages
|
||||
*/
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
/* Reduce object page count */
|
||||
BUG_ON(--vm_obj->npages < 0);
|
||||
|
||||
@@ -220,7 +220,7 @@ struct vm_file *shm_new(key_t key, unsigned long npages)
|
||||
* Fast internal path to do shmget/shmat() together for mm0's
|
||||
* convenience. Works for existing areas.
|
||||
*/
|
||||
void *shmat_shmget_internal(key_t key, void *shmaddr)
|
||||
void *shmat_shmget_internal(struct tcb *task, key_t key, void *shmaddr)
|
||||
{
|
||||
struct vm_file *shm_file;
|
||||
struct shm_descriptor *shm_desc;
|
||||
@@ -230,7 +230,7 @@ void *shmat_shmget_internal(key_t key, void *shmaddr)
|
||||
/* Found the key, shmat that area */
|
||||
if (shm_desc->key == key)
|
||||
return do_shmat(shm_file, shmaddr,
|
||||
0, find_task(self_tid()));
|
||||
0, task);
|
||||
}
|
||||
|
||||
return PTR_ERR(-EEXIST);
|
||||
|
||||
@@ -512,6 +512,27 @@ void init_pm(struct initdata *initdata)
|
||||
start_boot_tasks(initdata);
|
||||
}
|
||||
|
||||
/* Maps and prefaults the utcb of a task into another task */
|
||||
void task_map_prefault_utcb(struct tcb *mapper, struct tcb *owner)
|
||||
{
|
||||
BUG_ON(!owner->utcb);
|
||||
|
||||
/*
|
||||
* First internally map the tcb as a shm area. We use
|
||||
* such posix semantics on purpose to have a unified
|
||||
* way of doing similar operations.
|
||||
*/
|
||||
BUG_ON(IS_ERR(shmat_shmget_internal(mapper,
|
||||
(key_t)owner->utcb,
|
||||
owner->utcb)));
|
||||
|
||||
/* Prefault the owner's utcb to mapper's address space */
|
||||
for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++)
|
||||
prefault_page(mapper, (unsigned long)owner->utcb +
|
||||
__pfn_to_addr(i), VM_READ | VM_WRITE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* During its initialisation FS0 wants to learn how many boot tasks
|
||||
* are running, and their tids, which includes itself. This function
|
||||
@@ -535,7 +556,7 @@ int send_task_data(l4id_t requester)
|
||||
BUG_ON(!vfs->utcb);
|
||||
|
||||
/* Attach mm0 to vfs's utcb segment just like a normal task */
|
||||
BUG_ON(IS_ERR(shmat_shmget_internal((key_t)vfs->utcb, vfs->utcb)));
|
||||
BUG_ON(IS_ERR(shmat_shmget_internal(self, (key_t)vfs->utcb, vfs->utcb)));
|
||||
|
||||
/* Prefault those pages to self. */
|
||||
for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++)
|
||||
|
||||
Reference in New Issue
Block a user