patch-2.3.42 linux/arch/sparc64/mm/asyncd.c
Next file: linux/arch/sparc64/solaris/misc.c
Previous file: linux/arch/sparc64/mm/Makefile
Back to the patch index
Back to the overall index
- Lines: 284
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.41/linux/arch/sparc64/mm/asyncd.c
- Orig date:
Fri Jan 28 15:09:07 2000
diff -u --recursive --new-file v2.3.41/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c
@@ -1,283 +0,0 @@
-/* $Id: asyncd.c,v 1.12 2000/01/21 11:39:13 jj Exp $
- * The asyncd kernel daemon. This handles paging on behalf of
- * processes that receive page faults due to remote (async) memory
- * accesses.
- *
- * Idea and skeleton code courtesy of David Miller (bless his cotton socks)
- *
- * Implemented by tridge
- */
-
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/swap.h>
-#include <linux/fs.h>
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-
-#include <asm/dma.h>
-#include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
-#include <asm/bitops.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-
-#define DEBUG 0
-
-#define WRITE_LIMIT 100
-#define LOOP_LIMIT 200
-
-static struct {
- int faults, read, write, success, failure, errors;
-} stats;
-
-/*
- * The wait queue for waking up the async daemon:
- */
-static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait);
-
-struct async_job {
- volatile struct async_job *next;
- int taskid;
- struct mm_struct *mm;
- unsigned long address;
- int write;
- void (*callback)(int,unsigned long,int,int);
-};
-
-static volatile struct async_job *async_queue = NULL;
-static volatile struct async_job *async_queue_end = NULL;
-
-static void add_to_async_queue(int taskid,
- struct mm_struct *mm,
- unsigned long address,
- int write,
- void (*callback)(int,unsigned long,int,int))
-{
- struct async_job *a = kmalloc(sizeof(*a),GFP_ATOMIC);
-
- if (!a) {
- printk("ERROR: out of memory in asyncd\n");
- a->callback(taskid,address,write,1);
- return;
- }
-
- if (write)
- stats.write++;
- else
- stats.read++;
-
- a->next = NULL;
- a->taskid = taskid;
- a->mm = mm;
- a->address = address;
- a->write = write;
- a->callback = callback;
-
- if (!async_queue) {
- async_queue = a;
- } else {
- async_queue_end->next = a;
- }
- async_queue_end = a;
-}
-
-
-void async_fault(unsigned long address, int write, int taskid,
- void (*callback)(int,unsigned long,int,int))
-{
-#warning Need some fixing here... -DaveM
- struct task_struct *tsk = current /* XXX task[taskid] */;
- struct mm_struct *mm = tsk->mm;
-
- stats.faults++;
-
-#if 0
- printk("paging in %x for task=%d\n",address,taskid);
-#endif
-
- add_to_async_queue(taskid, mm, address, write, callback);
- wake_up(&asyncd_wait);
- mark_bh(TQUEUE_BH);
-}
-
-static int fault_in_page(int taskid,
- struct vm_area_struct *vma,
- unsigned long address, int write)
-{
- static unsigned last_address;
- static int last_task, loop_counter;
- siginfo_t info;
-#warning Need some fixing here... -DaveM
- struct task_struct *tsk = current /* XXX task[taskid] */;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- if (!tsk || !tsk->mm)
- return 1;
-
- if (!vma || (write && !(vma->vm_flags & VM_WRITE)))
- goto bad_area;
- if (vma->vm_start > address)
- goto bad_area;
-
- if (address == last_address && taskid == last_task) {
- loop_counter++;
- } else {
- loop_counter = 0;
- last_address = address;
- last_task = taskid;
- }
-
- if (loop_counter == WRITE_LIMIT && !write) {
- printk("MSC bug? setting write request\n");
- stats.errors++;
- write = 1;
- }
-
- if (loop_counter == LOOP_LIMIT) {
- printk("MSC bug? failing request\n");
- stats.errors++;
- return 1;
- }
-
- pgd = pgd_offset(vma->vm_mm, address);
- pmd = pmd_alloc(pgd,address);
- if(!pmd)
- goto no_memory;
- pte = pte_alloc(pmd, address);
- if(!pte)
- goto no_memory;
- if(!pte_present(*pte)) {
- handle_mm_fault(tsk, vma, address, write);
- goto finish_up;
- }
- set_pte(pte, pte_mkyoung(*pte));
- flush_tlb_page(vma, address);
- if(!write)
- goto finish_up;
- if(pte_write(*pte)) {
- set_pte(pte, pte_mkdirty(*pte));
- flush_tlb_page(vma, address);
- goto finish_up;
- }
- handle_mm_fault(tsk, vma, address, write);
-
- /* Fall through for do_wp_page */
-finish_up:
- stats.success++;
- return 0;
-
-no_memory:
- stats.failure++;
- oom(tsk);
- return 1;
-
-bad_area:
- stats.failure++;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *)address;
- info.si_trapno = 0;
- send_sig_info(SIGSEGV, &info, tsk);
- return 1;
-}
-
-
-/* Note the semaphore operations must be done here, and _not_
- * in async_fault().
- */
-static void run_async_queue(void)
-{
- int ret;
- unsigned flags;
-
- while (async_queue) {
- volatile struct async_job *a;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
-
- save_flags(flags); cli();
- a = async_queue;
- async_queue = async_queue->next;
- restore_flags(flags);
-
- mm = a->mm;
-
- down(&mm->mmap_sem);
- vma = find_vma(mm, a->address);
- ret = fault_in_page(a->taskid,vma,a->address,a->write);
-#if DEBUG
- printk("fault_in_page(task=%d addr=%x write=%d) = %d\n",
- a->taskid,a->address,a->write,ret);
-#endif
- a->callback(a->taskid,a->address,a->write,ret);
- up(&mm->mmap_sem);
- kfree_s((void *)a,sizeof(*a));
- }
-}
-
-
-#if CONFIG_AP1000
-static void asyncd_info(void)
-{
- printk("CID(%d) faults: total=%d read=%d write=%d success=%d fail=%d err=%d\n",
- mpp_cid(),stats.faults, stats.read, stats.write, stats.success,
- stats.failure, stats.errors);
-}
-#endif
-
-
-/*
- * The background async daemon.
- * Started as a kernel thread from the init process.
- */
-int asyncd(void *unused)
-{
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "asyncd");
-
- sigfillset(¤t->blocked); /* block all signals */
- recalc_sigpending(current);
-
- /* Give asyncd a realtime priority. */
- current->policy = SCHED_FIFO;
- current->priority = 32; /* Fixme --- we need to standardise our
- namings for POSIX.4 realtime scheduling
- priorities. */
-
- printk("Started asyncd\n");
-
-#if CONFIG_AP1000
- bif_add_debug_key('a',asyncd_info,"stats on asyncd");
-#endif
-
- while (1) {
- unsigned flags;
-
- save_flags(flags); cli();
-
- while (!async_queue) {
- spin_lock(¤t->sigmask_lock);
- flush_signals(current);
- spin_unlock(¤t->sigmask_lock);
- interruptible_sleep_on(&asyncd_wait);
- __sti(); cli(); /* acquire gloabl_irq_lock */
- }
-
- restore_flags(flags);
-
- run_async_queue();
- }
-}
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)