From 94fc97f703c625dd09edde4a3b9997b20e51b363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 5 Oct 2002 19:45:31 +0000 Subject: [PATCH] Return type of thread_set_priority() was wrong. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1395 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/core/debug.c | 2 +- src/kernel/core/elf.c | 4 +- src/kernel/core/fs/vfs.c | 39 ++++++-- src/kernel/core/main.c | 9 ++ src/kernel/core/thread.c | 2 +- src/kernel/core/vm/vm_page.c | 169 +++++++++++++++++++++++++++++++---- 6 files changed, 197 insertions(+), 28 deletions(-) diff --git a/src/kernel/core/debug.c b/src/kernel/core/debug.c index f0d77dbb85..e608b78943 100644 --- a/src/kernel/core/debug.c +++ b/src/kernel/core/debug.c @@ -244,7 +244,7 @@ kernel_debugger(const char * message) dprintf(message); dprintf("\n"); }; - + dprintf("Welcome to Kernel Debugging Land...\n"); kernel_debugger_loop(); } diff --git a/src/kernel/core/elf.c b/src/kernel/core/elf.c index 09a89906a1..54fb0df58f 100644 --- a/src/kernel/core/elf.c +++ b/src/kernel/core/elf.c @@ -49,7 +49,7 @@ struct elf_image_info { struct elf_linked_image *linked_images; struct Elf32_Ehdr *eheader; - + // pointer to symbol participation data structures char *needed; unsigned int *symhash; @@ -1082,8 +1082,8 @@ elf_init(kernel_args *ka) mutex_init(&image_load_lock, "kimages_load_lock"); // build a image structure for the kernel, which has already been loaded + kernel_image = create_image_struct(); - kernel_image->name = kstrdup("kernel"); // text segment diff --git a/src/kernel/core/fs/vfs.c b/src/kernel/core/fs/vfs.c index 913efcf516..d2137a3060 100755 --- a/src/kernel/core/fs/vfs.c +++ b/src/kernel/core/fs/vfs.c @@ -236,6 +236,21 @@ struct fd_ops gIndexDirectoryOps = { }; +static void +check_wall(int32 line, void *address) +{ +// uint32 *wall = (uint32 *)((uint8 *)address - 12); +// uint32 size = wall[0]; +// +// if (wall[1] != 0xabadcafe || wall[2] != 0xabadcafe) +// panic("check_wall: line %ld, front wall was overwritten (allocation at %p, %lu bytes): %08lx %08lx\n", line, address, size, wall[1], wall[2]); +// +// wall = (uint32 *)((uint8 *)address + size); +// if (wall[0] != 0xabadcafe || wall[1] != 0xabadcafe) +// panic("check_wall: line %ld, back wall was overwritten (allocation at %p, %lu bytes): %08lx %08lx\n", line, address, size, wall[0], wall[1]); +} + + static int mount_compare(void *_m, const void *_key) { @@ -508,6 +523,8 @@ dec_vnode_ref_count(struct vnode *vnode, bool reenter) int err; int old_ref; +check_wall(__LINE__, vnode); + mutex_lock(&gVnodeMutex); if (vnode->busy == true) @@ -539,6 +556,7 @@ dec_vnode_ref_count(struct vnode *vnode, bool reenter) mutex_unlock(&gVnodeMutex); kfree(vnode); + err = 1; } else { mutex_unlock(&gVnodeMutex); @@ -598,12 +616,14 @@ get_vnode(mount_id mountID, vnode_id vnodeID, struct vnode **_vnode, int reenter } else { // we need to create a new vnode and read it in vnode = create_new_vnode(); +check_wall(__LINE__, vnode); if (!vnode) { - err = ENOMEM; + err = B_NO_MEMORY; goto err; } vnode->mount_id = mountID; vnode->id = vnodeID; +check_wall(__LINE__, vnode); mutex_lock(&gMountMutex); @@ -613,6 +633,7 @@ get_vnode(mount_id mountID, vnode_id vnodeID, struct vnode **_vnode, int reenter err = ERR_INVALID_HANDLE; goto err; } +check_wall(__LINE__, vnode); vnode->busy = true; hash_insert(gVnodeTable, vnode); mutex_unlock(&gVnodeMutex); @@ -620,6 +641,7 @@ get_vnode(mount_id mountID, vnode_id vnodeID, struct vnode **_vnode, int reenter add_vnode_to_mount_list(vnode, vnode->mount); mutex_unlock(&gMountMutex); +check_wall(__LINE__, vnode); err = FS_CALL(vnode, get_vnode)(vnode->mount->cookie, vnodeID, &vnode->private_node, reenter); if (err < 0 && vnode->private_node == NULL) { remove_vnode_from_mount_list(vnode, vnode->mount); @@ -632,6 +654,7 @@ get_vnode(mount_id mountID, vnode_id vnodeID, struct vnode **_vnode, int reenter vnode->busy = false; vnode->ref_count = 1; +check_wall(__LINE__, vnode); } mutex_unlock(&gVnodeMutex); @@ -694,10 +717,12 @@ entry_ref_to_vnode(mount_id mountID, vnode_id directoryID, const char *name, str } -static int +static status_t vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink, struct vnode **_vnode, int count) { - int status = 0; + status_t status = 0; + + FUNCTION(("vnode_path_to_vnode(path = %s)\n", path)); if (!path) return EINVAL; @@ -742,6 +767,7 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink, stru put_vnode(vnode); return status; } +check_wall(__LINE__, vnode); // lookup the vnode, the call to fs_lookup should have caused a get_vnode to be called // from inside the filesystem, thus the vnode would have to be in the list and it's @@ -833,8 +859,8 @@ static int path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel) { struct vnode *start; - int linkCount = 0; - int status = 0; + + FUNCTION(("path_to_vnode(path = %s)\n", path)); if (!path) return EINVAL; @@ -853,6 +879,7 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel) inc_vnode_ref_count(start); mutex_unlock(&context->io_mutex); } +check_wall(__LINE__, start); return vnode_path_to_vnode(start, path, traverseLink, _vnode, 0); } @@ -868,6 +895,8 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel { char *p = strrchr(path, '/'); + FUNCTION(("path_to_dir_vnode(path = %s)\n", path)); + if (!p) { // this path is single segment with no '/' in it // ex. "foo" diff --git a/src/kernel/core/main.c b/src/kernel/core/main.c index 2ea73eb8bf..49a25c6df8 100644 --- a/src/kernel/core/main.c +++ b/src/kernel/core/main.c @@ -118,12 +118,18 @@ static int main2(void *unused) dprintf("start of main2: initializing devices\n"); /* bootstrap all the filesystems */ +dprintf("******************** a ********************\n"); vfs_bootstrap_all_filesystems(); +dprintf("******************** b ********************\n"); module_init(&ka, NULL); +dprintf("******************** c ********************\n"); bus_init(&ka); +dprintf("******************** d ********************\n"); dev_init(&ka); +dprintf("******************** e ********************\n"); con_init(&ka); +dprintf("******************** f ********************\n"); //net_init_postdev(&ka); #if 0 @@ -150,9 +156,12 @@ static int main2(void *unused) { team_id pid; pid = team_create_team("/boot/bin/init", "init", NULL, 0, NULL, 0, 5); +dprintf("******************** g ********************\n"); if (pid < 0) kprintf("error starting 'init' error = %ld \n", pid); +dprintf("******************** h ********************\n"); } +dprintf("******************** i ********************\n"); return 0; } diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index a4ed9c4da5..d4552f05aa 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -531,7 +531,7 @@ thread_resume_thread(thread_id id) } #ifndef NEW_SCHEDULER -int +status_t thread_set_priority(thread_id id, int32 priority) { struct thread *t; diff --git a/src/kernel/core/vm/vm_page.c b/src/kernel/core/vm/vm_page.c index 911d90340a..a059425cb9 100755 --- a/src/kernel/core/vm/vm_page.c +++ b/src/kernel/core/vm/vm_page.c @@ -18,6 +18,7 @@ #include #include +#include typedef struct page_queue { vm_page *head; @@ -40,66 +41,136 @@ static spinlock_t page_lock; static sem_id modified_pages_available; +static int dump_page(int argc, char **argv); +static int dump_page_queue(int argc, char **argv); static int dump_page_stats(int argc, char **argv); static int dump_free_page_table(int argc, char **argv); static int vm_page_set_state_nolock(vm_page *page, int page_state); static void clear_page(addr pa); static int page_scrubber(void *); +static bool gCheck = false; + + +static void +check_page_queue(const char *prefix, page_queue *queue) +{ + vm_page *page; + + if (!gCheck) + return; + + for (page = queue->head; page; page = page->queue_next) { + if (page->queue_next == NULL && queue->tail != page) + panic("check_page: \"%s\", q = %p, page = %p\n", prefix, queue, page); + } +} + + static vm_page *dequeue_page(page_queue *q) { vm_page *page; + check_page_queue("dq1", q); +// dprintf("dequeue_page: q = %p, q->head = %p, q->tail = %p\n", q, q->head, q->tail); + if ((q->head == NULL || q->tail == NULL) && q->head != q->tail) + panic("dequeue_page1: list at %p is corrupt (count = %d)\n", q, q->count); + page = q->tail; - if(page != NULL) { - if(q->head == page) + if (page != NULL) { + if (page->queue_prev == NULL && q->head != page) + panic("dp: q = %p, page = %p, page->queue_prev == NULL, but q->head != page\n", q, page); + if (page->queue_next == NULL && q->tail != page) + panic("dp: q = %p, page = %p, page->queue_next == NULL, but q->tail != page\n", q, page); + + if (q->head == page) { + dprintf("dequeue: q = %p, set head to NULL\n", q); q->head = NULL; - if(page->queue_prev != NULL) { + } + if (page->queue_prev != NULL) { page->queue_prev->queue_next = NULL; } q->tail = page->queue_prev; q->count--; + } else if (q->head != NULL) + panic("dequeue_page: list %p is corrupt\n", q); + + if ((q->head == NULL || q->tail == NULL) && q->head != q->tail) { + dprintf("page = %p, page->prev = %p, page->next = %p\n", page, page->queue_prev, page->queue_next); + dprintf("q = %p, q->head = %p, q->tail = %p, q->count = %d\n", q, q->head, q->tail, q->count); + panic("dequeue_page2: list at %p is corrupt (count = %d)\n", q, q->count); } + + check_page_queue("dq2", q); + return page; } static void enqueue_page(page_queue *q, vm_page *page) { - if(q->head != NULL) + check_page_queue("eq1", q); + +// dprintf("enqueue_page: q = %p, q->head = %p, q->tail = %p\n", q, q->head, q->tail); + if ((q->head == NULL || q->tail == NULL) && q->head != q->tail) + panic("enqueue_page: list at %p is corrupt (count = %d)\n", q, q->count); + + if (q->head != NULL) q->head->queue_prev = page; page->queue_next = q->head; q->head = page; page->queue_prev = NULL; - if(q->tail == NULL) + if (q->tail == NULL) q->tail = page; q->count++; - if(q == &page_modified_queue) { - if(q->count == 1) + if (q == &page_modified_queue) { + if (q->count == 1) release_sem_etc(modified_pages_available, 1, B_DO_NOT_RESCHEDULE); } + + if (page->queue_prev == NULL && q->head != page) + panic("ep: q = %p, page = %p, page->queue_prev == NULL, but q->head != page\n", q, page); + if (page->queue_next == NULL && q->tail != page) + panic("ep: q = %p, page = %p, page->queue_next == NULL, but q->tail != page\n", q, page); + + if ((q->head == NULL || q->tail == NULL) && q->head != q->tail) + panic("enqueue_page: list at %p is corrupt (count = %d)\n", q, q->count); + + check_page_queue("eq2", q); } static void remove_page_from_queue(page_queue *q, vm_page *page) { - if(page->queue_prev != NULL) { +// dprintf("remove_page: q = %p, q->head = %p, q->tail = %p\n", q, q->head, q->tail); + check_page_queue("rpq1", q); + + if (page->queue_prev != NULL) { page->queue_prev->queue_next = page->queue_next; } else { q->head = page->queue_next; } - if(page->queue_next != NULL) { + if (page->queue_next != NULL) { page->queue_next->queue_prev = page->queue_prev; } else { q->tail = page->queue_prev; } q->count--; + + if ((q->head == NULL || q->tail == NULL) && q->head != q->tail) + panic("remove_page_from_queue: list at %p is corrupt (count = %d)\n", q, q->count); + + check_page_queue("rpq2", q); } static void move_page_to_queue(page_queue *from_q, page_queue *to_q, vm_page *page) { - if(from_q != to_q) { + if (from_q != to_q) { remove_page_from_queue(from_q, page); enqueue_page(to_q, page); } + if ((from_q->head == NULL || from_q->tail == NULL) && from_q->head != from_q->tail) + panic("move_page_to_queue: from list at %p is corrupt (count = %d)\n", from_q, from_q->count); + if ((to_q->head == NULL || to_q->tail == NULL) && to_q->head != to_q->tail) + panic("move_page_to_queue: to list at %p is corrupt (count = %d)\n", to_q, to_q->count); } static int pageout_daemon() @@ -234,6 +305,7 @@ int vm_page_init(kernel_args *ka) vm_mark_page_range_inuse(ka->phys_alloc_range[i].start / PAGE_SIZE, ka->phys_alloc_range[i].size / PAGE_SIZE); } + gCheck = true; // set the global max_commit variable vm_increase_max_commit(num_pages*PAGE_SIZE); @@ -253,6 +325,8 @@ int vm_page_init2(kernel_args *ka) add_debugger_command("page_stats", &dump_page_stats, "Dump statistics about page usage"); add_debugger_command("free_pages", &dump_free_page_table, "Dump list of free pages"); + add_debugger_command("page", &dump_page, "Dump page info"); + add_debugger_command("page_queue", &dump_page_queue, "Dump page queue"); return 0; } @@ -417,20 +491,20 @@ vm_page *vm_page_allocate_specific_page(addr page_num, int page_state) // we can't allocate this page p = NULL; } - if(p == NULL) + if (p == NULL) goto out; old_page_state = p->state; p->state = PAGE_STATE_BUSY; - if(old_page_state != PAGE_STATE_UNUSED) + if (old_page_state != PAGE_STATE_UNUSED) enqueue_page(&page_active_queue, p); out: release_spinlock(&page_lock); restore_interrupts(state); - if(p != NULL && page_state == PAGE_STATE_CLEAR && + if (p != NULL && page_state == PAGE_STATE_CLEAR && (old_page_state == PAGE_STATE_FREE || old_page_state == PAGE_STATE_UNUSED)) { clear_page(p->ppn * PAGE_SIZE); @@ -464,12 +538,13 @@ vm_page *vm_page_allocate_page(int page_state) acquire_spinlock(&page_lock); p = dequeue_page(q); - if(p == NULL) { - // the clear queue was empty, grab one from the free queue and zero it out + if (p == NULL) { + // if the primary queue was empty, grap the page from the + // secondary queue p = dequeue_page(q_other); - if(p == NULL) { + if (p == NULL) { // XXX hmm - panic("vm_allocate_page: out of memory!\n"); + panic("vm_allocate_page: out of memory! page state = %d\n", page_state); } } @@ -481,9 +556,9 @@ vm_page *vm_page_allocate_page(int page_state) release_spinlock(&page_lock); restore_interrupts(state); - if(page_state == PAGE_STATE_CLEAR && old_page_state == PAGE_STATE_FREE) { + // if needed take the page from the free queue and zero it out + if (page_state == PAGE_STATE_CLEAR && old_page_state == PAGE_STATE_FREE) clear_page(p->ppn * PAGE_SIZE); - } return p; } @@ -626,6 +701,56 @@ static int dump_free_page_table(int argc, char **argv) return 0; } + +static int +dump_page(int argc, char **argv) +{ + struct vm_page *page; + + if (argc < 2 + || strlen(argv[1]) <= 2 + || argv[1][0] != '0' + || argv[1][1] != 'x') { + dprintf("usage: page_queue
\n"); + return 0; + } + + page = (struct vm_page *)(atoul(argv[1])); + + dprintf("queue_next = %p, queue_prev = %p, type = %d, state = %d\n", page->queue_next, page->queue_prev, page->type, page->state); + return 0; +} + + +static int +dump_page_queue(int argc, char **argv) +{ + struct page_queue *queue; + + if (argc < 2 + || strlen(argv[1]) <= 2 + || argv[1][0] != '0' + || argv[1][1] != 'x') { + dprintf("usage: page_queue
[list]\n"); + return 0; + } + + queue = (struct page_queue *)(atoul(argv[1])); + + dprintf("queue->head = %p, queue->tail = %p, queue->count = %d\n", queue->head, queue->tail, queue->count); + + if (argc == 3) { + struct vm_page *page = queue->head; + int i; + + for (i = 0; page; i++, page = page->queue_next) { + dprintf("%5d. queue_next = %p, queue_prev = %p, type = %d, state = %d\n", i, page->queue_next, page->queue_prev, page->type, page->state); + } + } + return 0; +} + + static int dump_page_stats(int argc, char **argv) { unsigned int page_types[8]; @@ -642,6 +767,12 @@ static int dump_page_stats(int argc, char **argv) page_types[PAGE_STATE_ACTIVE], page_types[PAGE_STATE_INACTIVE], page_types[PAGE_STATE_BUSY], page_types[PAGE_STATE_UNUSED]); dprintf("modified: %d\nfree: %d\nclear: %d\nwired: %d\n", page_types[PAGE_STATE_MODIFIED], page_types[PAGE_STATE_FREE], page_types[PAGE_STATE_CLEAR], page_types[PAGE_STATE_WIRED]); + + dprintf("\nfree_queue: %p, count = %d\n", &page_free_queue, page_free_queue.count); + dprintf("clear_queue: %p, count = %d\n", &page_clear_queue, page_clear_queue.count); + dprintf("modified_queue: %p, count = %d\n", &page_modified_queue, page_modified_queue.count); + dprintf("active_queue: %p, count = %d\n", &page_active_queue, page_active_queue.count); + return 0; }