Changeset 16

Show
Ignore:
Timestamp:
10/29/05 20:46:21 (6 years ago)
Author:
dkaplan1
Message:

Added thread pool. Process startup and cleanup seems pretty smooth. NOTE
this code experiences a BUG as documented about exec's failing ~10 seconds
after a rmmod

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • arch/i386/kernel/callgate.c

    r15 r16  
    6464void *ring1_driver_helper; 
    6565void *ring2_driver_helper; 
     66void *ring1_nop; 
     67void *ring2_nop; 
    6668 
    6769void callgate_entry1(int oldcs, unsigned long param1); 
     
    212214        "ud2\n" 
    213215        ".previous"); 
     216 
     217extern void ring_nop(void); 
     218extern void end_of_nop(void); 
     219__asm__("ring_nop : ret \n\t" 
     220        "end_of_nop:ud2\n\t"); 
    214221void create_driver_helpers(void) 
    215222{ 
     
    220227    memcpy(ring1_driver_helper, driver_thread_helper, size_of_asm); 
    221228    memcpy(ring2_driver_helper, driver_thread_helper, size_of_asm); 
     229    size_of_asm=end_of_nop - ring_nop; 
     230     
     231    ring1_nop=__vmalloc(size_of_asm, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1); 
     232    ring2_nop=__vmalloc(size_of_asm, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2); 
     233     
     234    memcpy(ring1_nop, ring_nop, size_of_asm); 
     235    memcpy(ring2_nop, ring_nop, size_of_asm); 
    222236    create_callgate((unsigned long) callgate_entry1, 2, 1); 
    223237    create_callgate((unsigned long) callgate_entry2, 2, 2); 
     
    257271    if (!tsk) { 
    258272        printk(KERN_ERR "Could not find worker thread for address %x\n", addr); 
    259         return -1; 
     273        printk(KERN_ERR "Probably all threads are currently in use, try increasing size of driver thread pool\n"); 
     274        return -EBUSY; 
    260275    } 
    261276    if (tsk->flags & PF_DEAD) { 
     
    263278        return -ENODEV; 
    264279    } 
    265     if (!tsk->available) { 
     280    /*if (!tsk->available) { 
    266281        printk(KERN_ERR "Thread busy...increase size of driver thread pool\n"); 
    267282        return -1; 
    268     } 
     283    }*/ 
    269284    tsk->available=0; 
    270285    //Set memory map 
    271286    if (mm) { 
     287        atomic_dec(&tsk->mm->mm_users); 
     288        atomic_dec(&tsk->mm->mm_count); 
    272289        atomic_inc(&mm->mm_users); 
    273290        atomic_inc(&mm->mm_count); 
  • arch/i386/kernel/process.c

    r15 r16  
    6262extern void *ring1_driver_helper; 
    6363extern void *ring2_driver_helper; 
     64 
     65extern void driver_exit(int error_code); 
    6466 
    6567 
     
    347349} 
    348350*/ 
     351extern void *ring1_nop; 
     352extern void *ring2_nop; 
    349353int create_driver_thread(unsigned long flags, int ring) 
    350354{ 
     
    354358  int pid; 
    355359        memset(&regs, 0, sizeof(regs)); 
    356 //      regs.ebx = (unsigned long) fn; 
     360         
    357361//      regs.edx = (unsigned long) arg; 
    358362 
     
    365369      regs.xcs = __RING1_CS; 
    366370      regs.xss = __RING1_DS; 
    367   //    regs.eip = (unsigned long) ring1_driver_helper; 
     371      regs.ebx= (unsigned long) ring1_nop; 
     372      regs.eip = (unsigned long) ring1_driver_helper; 
    368373      orig_stack= __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1); 
    369374  //    printk("Created ring 1 stack at %x", stack_start); 
     
    375380      regs.xcs = __RING2_CS; 
    376381      regs.xss = __RING2_DS; 
     382      regs.ebx=(unsigned long) ring2_nop; 
    377383      regs.eip = (unsigned long) ring2_driver_helper; 
    378384      orig_stack= __vmalloc(8192, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING2); 
     
    389395        /* Ok, create the new process.. */ 
    390396  //printk("Calling do_fork"); 
    391         pid=do_fork(flags | CLONE_STOPPED | CLONE_VM | CLONE_UNTRACED | CLONE_PARENT, (unsigned long) stack_start, &regs, 0, NULL, NULL); 
     397        pid=do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_PARENTINIT  , (unsigned long) stack_start, &regs, 0, NULL, NULL); 
    392398  find_task_by_pid(pid)->orig_stack=orig_stack; 
    393   find_task_by_pid(pid)->available=1
     399  find_task_by_pid(pid)->available=0
    394400  return pid; 
    395401} 
  • arch/i386/kernel/signal.c

    r15 r16  
    560560         */ 
    561561//      if ((regs->xcs & 3) != 3) 
    562   if ((regs->xcs & 3)==1) 
    563       printk("Sending signal to ring 1 driver thread!\n"); 
    564562  if (!(regs->xcs & 3)) 
    565563                return 1; 
  • arch/i386/kernel/traps.c

    r15 r16  
    2727#include <linux/ptrace.h> 
    2828#include <linux/version.h> 
     29#include <linux/syscalls.h> 
    2930 
    3031#ifdef CONFIG_EISA 
     
    437438DO_ERROR(12, SIGBUS,  "stack segment", stack_segment) 
    438439DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) 
     440void do_unload_module(void *myaddr) { 
     441    char *name; 
     442    int ret; 
     443    unsigned long addr=(unsigned long) myaddr; 
     444    printk("Attempting to unload module\n"); 
     445    name=find_module_by_thread(addr); 
     446    printk("Address we got was %x, module is %s\n", addr, name); 
     447    ret=sys_delete_module(name, 0); 
     448    printk("delete returned %d which is %d", ret, -ret); 
     449} 
     450static DECLARE_WORK(mytask, do_unload_module, NULL); 
     451static struct workqueue_struct *mywq; 
    439452asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) 
    440453{ 
     
    454467      current->thread.error_code=error_code; 
    455468      current->thread.trap_no=13; 
     469      current->exit_signal=-1; 
    456470      force_sig(SIGKILL, current); 
     471      printk("Unloading module cleanly...\n"); 
     472      mywq=create_workqueue("gp"); 
     473      mytask.data=(void*) regs->eip; 
     474      //queue_work(mywq, &mytask); 
    457475      return; 
    458476           
  • include/linux/module.h

    r14 r16  
    2828#define MODULE_SUPPORTED_DEVICE(name) 
    2929 
     30//Number of threads in driver thread pool 
     31#define NR_DRIVERTHREADS 10 
     32 
    3033/* v850 toolchain uses a `_' prefix for all user symbols */ 
    3134#ifndef MODULE_SYMBOL_PREFIX 
     
    5255 
    5356extern struct task_struct *find_worker_thread(unsigned long addr); 
     57extern char *find_module_by_thread(unsigned long addr); 
    5458 
    5559/* Archs provide a method of finding the correct exception table. */ 
     
    317321 
    318322  /*task struct of worker thread*/ 
    319   struct task_struct *worker_thread
     323  struct task_struct *worker_threads[NR_DRIVERTHREADS]
    320324 
    321325  /*ring we got loaded in*/ 
  • include/linux/sched.h

    r8 r16  
    5555#define CLONE_CHILD_SETTID      0x01000000      /* set the TID in the child */ 
    5656#define CLONE_STOPPED           0x02000000      /* Start in stopped state */ 
    57  
     57#define CLONE_PARENTINIT 0x04000000 
    5858/* 
    5959 * List of flags we want to share for kernel threads, 
     
    739739extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state)); 
    740740extern int FASTCALL(wake_up_process(struct task_struct * tsk)); 
    741 extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk)); 
     741extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk, unsigned long clone_flags)); 
    742742#ifdef CONFIG_SMP 
    743743 extern void kick_process(struct task_struct *tsk); 
     
    745745#else 
    746746 static inline void kick_process(struct task_struct *tsk) { } 
    747  static inline void wake_up_forked_thread(struct task_struct * tsk
     747 static inline void wake_up_forked_thread(struct task_struct * tsk, unsigned long clone_flags
    748748 { 
    749         wake_up_forked_process(tsk); 
     749        wake_up_forked_process(tsk, clone_flags); 
    750750 } 
    751751#endif 
  • kernel/fork.c

    r15 r16  
    10481048        if (clone_flags & CLONE_PARENT) 
    10491049                p->real_parent = current->real_parent; 
     1050  else if (clone_flags & CLONE_PARENTINIT) 
     1051      p->real_parent=&init_task; 
    10501052        else 
    10511053                p->real_parent = current; 
     
    12021204                         * We'll start up with an immediate SIGSTOP. 
    12031205                         */ 
    1204                 /*    sigaddset(&p->pending.signal, SIGSTOP); 
    1205                         set_tsk_thread_flag(p, TIF_SIGPENDING);*/ 
     1206                      sigaddset(&p->pending.signal, SIGSTOP); 
     1207                        set_tsk_thread_flag(p, TIF_SIGPENDING); 
    12061208                } 
    12071209 
     
    12191221                         */ 
    12201222                        if (clone_flags & CLONE_VM) 
    1221                                 wake_up_forked_thread(p); 
     1223                                wake_up_forked_thread(p, clone_flags); 
    12221224                        else 
    1223                                 wake_up_forked_process(p); 
     1225                                wake_up_forked_process(p, clone_flags); 
    12241226        //      } else { 
    12251227if (clone_flags & CLONE_STOPPED) { 
    12261228                        int cpu = get_cpu(); 
    12271229 
    1228                         p->state = TASK_STOPPED; 
     1230                        //p->state = TASK_STOPPED; 
    12291231                        if (cpu_is_offline(task_cpu(p))) 
    12301232                                set_task_cpu(p, cpu); 
  • kernel/module.c

    r15 r16  
    562562        int ret, forced = 0; 
    563563  unsigned long testargs; 
     564  int i; 
    564565        if (!capable(CAP_SYS_MODULE)) 
    565566                return -EPERM; 
    566  
    567         if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) 
    568                 return -EFAULT; 
     567   
     568  if ((unsigned long) name_user < TASK_SIZE ) { 
     569      if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) 
     570          return -EFAULT; 
     571  } else { 
     572      if (strncpy(name, name_user, MODULE_NAME_LEN -1 ) < 0) 
     573          return -EFAULT; 
     574  } 
    569575        name[MODULE_NAME_LEN-1] = '\0'; 
    570576 
     
    577583                goto out; 
    578584        } 
    579  
    580585        if (!list_empty(&mod->modules_which_use_me)) { 
    581586                /* Other modules depend on us: get rid of them first. */ 
     
    627632        down(&module_mutex); 
    628633  //NEW: get rid of threads 
    629   zap_other_threads(mod->worker_thread); 
    630   module_free(mod, mod->worker_thread->orig_stack); 
     634  for (i=0; i<NR_DRIVERTHREADS; i++) { 
     635      //zap_other_threads(mod->worker_threads[i]); 
     636      if (!(mod->worker_threads[i]->flags & PF_DEAD)) { 
     637          mod->worker_threads[i]->exit_signal=-1; 
     638          force_sig(SIGKILL, mod->worker_threads[i]); 
     639          wake_up_process(mod->worker_threads[i]); 
     640      } 
     641       
     642      module_free(mod, mod->worker_threads[i]->orig_stack); 
     643  } 
    631644        free_module(mod); 
     645  print_modules(); 
    632646        down(&notify_mutex); 
    633647        notifier_call_chain(&module_notify_list, MODULE_STATE_GONE, 
     
    14761490        /* Suck in entire file: we'll want most of it. */ 
    14771491        /* vmalloc barfs on "unusual" numbers.  Check here */ 
    1478 //     if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) 
     1492       //if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) 
    14791493        if (len > 64 * 1024 * 1024 || (hdr = __vmalloc(len, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, VMALLOC_RING1)) == NULL) 
    14801494                return ERR_PTR(-ENOMEM); 
     
    16041618 
    16051619        if (pcpuindex) { 
     1620    printk("wtf?\n"); 
    16061621                /* We have a special allocation for this section. */ 
    16071622                percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, 
     
    16141629                mod->percpu = percpu; 
    16151630        } 
     1631  //New 
     1632  else 
     1633      mod->percpu=0; 
    16161634 
    16171635        /* Determine total sizes, and put offsets in sh_entsize.  For now 
     
    16361654        memset(ptr, 0, mod->init_size); 
    16371655        mod->module_init = ptr; 
    1638  
     1656printk("percpu is currently %xn", mod->percpu); 
    16391657        /* Transfer each section which specifies SHF_ALLOC */ 
    16401658        DEBUGP("final section addresses:\n"); 
     
    16601678        /* Module has been moved. */ 
    16611679        mod = (void *)sechdrs[modindex].sh_addr; 
    1662  
     1680printk("NOW it is %x\n", mod->percpu); 
    16631681        /* Now we've moved module, initialize linked lists, etc. */ 
    16641682        module_unload_init(mod); 
     
    18081826        int ret; 
    18091827  int pid; 
     1828  int i; 
    18101829  /* Must have permission */ 
    18111830        if (!capable(CAP_SYS_MODULE)) 
    18121831                return -EPERM; 
    1813  
    18141832        /* Only one module load at a time, please */ 
    18151833        if (down_interruptible(&module_mutex) != 0) 
     
    18581876  //FIXME: Figure out what ring to load module in (how?) 
    18591877  mod->ring=1; 
    1860   pid=create_driver_thread(0, mod->ring); 
    1861   if (!pid) { 
    1862         printk("ERROR getting pid for worker thread\n"); 
    1863         //FIXME: Correct return code here? 
    1864       return -1; 
     1878  for (i=0; i<NR_DRIVERTHREADS; i++) { 
     1879      pid=create_driver_thread(0, mod->ring); 
     1880      if (!pid) { 
     1881          printk("ERROR getting pid for worker thread\n"); 
     1882          //FIXME: Correct return code here? 
     1883          return -1; 
     1884      } 
     1885      mod->worker_threads[i]=find_task_by_pid(pid); 
     1886      if (!mod->worker_threads[i]) { 
     1887          printk("ERROR getting task struct for worker thread\n"); 
     1888          return -1; 
     1889      } 
     1890      mod->worker_threads[i]->ring=mod->ring; 
    18651891  } 
    1866   mod->worker_thread=find_task_by_pid(pid); 
    1867   mod->worker_thread->ring=mod->ring; 
    1868   if (!mod->worker_thread) { 
    1869       printk("ERROR getting task struct for worker thread\n"); 
    1870       return -1; 
    1871   } 
     1892  schedule(); 
     1893  printk("mod pointer is %x, per cpu is %d\n", mod, mod->percpu); 
    18721894  printk("Invoking init method...\n"); 
    18731895  ret=calldriver((unsigned long) mod->init, NULL, 0, NULL, 0); 
     
    19161938    struct task_struct *tsk=NULL; 
    19171939    struct module *mod; 
     1940    int i=0; 
    19181941    if (!addr) 
    19191942        return NULL; 
     
    19221945    list_for_each_entry(mod, &modules, list) { 
    19231946        if (within(addr, mod->module_init, mod->init_size) || 
    1924                 within(addr, mod->module_core, mod->core_size)) 
    1925             tsk=mod->worker_thread; 
     1947                within(addr, mod->module_core, mod->core_size)) { 
     1948            //Now find an availalbe one 
     1949            while (i < NR_DRIVERTHREADS) { 
     1950                if (mod->worker_threads[i]->available) { 
     1951                    tsk=mod->worker_threads[i];  
     1952                    goto out; 
     1953                } 
     1954                i++; 
     1955            } 
     1956        } 
    19261957    } 
    19271958 
    1928  
     1959out: 
    19291960    spin_unlock_irq(&modlist_lock); 
    19301961    return tsk; 
     1962} 
     1963 
     1964char *find_module_by_thread(unsigned long addr) 
     1965{ 
     1966    struct module *mod; 
     1967    if (!addr) 
     1968        return NULL; 
     1969    spin_lock_irq(&modlist_lock); 
     1970    list_for_each_entry(mod, &modules, list) { 
     1971        if (within(addr, mod->module_init, mod->init_size) || 
     1972                within(addr, mod->module_core, mod->core_size)) { 
     1973            spin_unlock_irq(&modlist_lock); 
     1974            return mod->name; 
     1975        } 
     1976    } 
     1977    spin_unlock_irq(&modlist_lock); 
     1978    return NULL; 
    19311979} 
    19321980 
  • kernel/sched.c

    r1 r16  
    927927 * that must be done for every newly created process. 
    928928 */ 
    929 void fastcall wake_up_forked_process(task_t * p
     929void fastcall wake_up_forked_process(task_t * p, unsigned long clone_flags
    930930{ 
    931931        unsigned long flags; 
     
    949949        p->prio = effective_prio(p); 
    950950        set_task_cpu(p, smp_processor_id()); 
    951  
    952951        if (unlikely(!current->array)) 
    953952                __activate_task(p, rq); 
     
    12701269        p->prio = effective_prio(p); 
    12711270        set_task_cpu(p, cpu); 
    1272  
    12731271        if (cpu == this_cpu) { 
    12741272                if (unlikely(!current->array)) 
     
    12891287                        resched_task(rq->curr); 
    12901288        } 
    1291  
    12921289        double_rq_unlock(this_rq, rq); 
    12931290        local_irq_restore(flags); 
     
    39763973        rq->idle = current; 
    39773974        set_task_cpu(current, smp_processor_id()); 
    3978         wake_up_forked_process(current); 
     3975        wake_up_forked_process(current, 0); 
    39793976 
    39803977        /* 
  • .version

    r15 r16  
    1 146 
     1181