#include <linux/config.h>
#include <linux/version.h>

#include <linux/module.h>
#if defined(MODVERSIONS)
#include <linux/modversions.h>
#endif

#include <linux/delay.h>
#include <asm/unistd.h>
#include <linux/wait.h>
#include <linux/in.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>

#define MODULE_MAJOR 243
#define MODULE_NAME "KernelThread"


/* ######################################################################### */
/* # Structure for kthread                                                 # */
/* ######################################################################### */
typedef struct kthread_struct {
  /* a structure to store all information we need for our thread */
  /* private data */

  /* Linux task structure of thread */
  struct task_struct *
     thread;
  /* Task queue need to launch thread */
  struct tq_struct 
     tq;
  /* function to be started as thread */
  void (*function) 
     (struct kthread_struct *kthread);
  /* semaphore needed on start and creation of thread. */
  struct semaphore 
     startstop_sem;

  /* public data */

  /* queue thread is waiting on. Gets initialized by
     init_kthread, can be used by thread itself.
  */
  wait_queue_head_t 
    queue;
  /* flag to tell thread whether to die or not.
     When the thread receives a signal, it must check
     the value of terminate and call exit_kthread and terminate
     if set.
  */
  int 
     terminate;
  /* additional data to pass to kernel thread */
  void *
     arg;
} kthread_t;
/* ######################################################################### */

/* ######################################################################### */
/* #                                                                       # */
/* # Variables definitions                                                 # */
/* #                                                                       # */
/* ######################################################################### */
static kthread_t 
   KernelThreadStruct;
/* ######################################################################### */





/* ######################################################################### */
/* #                                                                       # */
/* # Private functions                                                     # */
/* #                                                                       # */
/* ######################################################################### */
/* #                                                                       # */
/* ######################################################################### */
/* #                                                                       # */
/* # Name             : kthread_launcher                                   # */
/* #                                                                       # */
/* # Description      : Laucher of kernel thread.                          # */
/* #                                                                       # */
/* # Input Parameters : void *data                                         # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          : Private                                            # */
/* #                                                                       # */
/* ######################################################################### */
static void kthread_launcher(void *data) {
  kthread_t *
     kthread = data;
  kernel_thread((int (*)(void *))kthread->function, (void *)kthread, 0);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Public functions                                                      # */
/* #                                                                       # */
/* ######################################################################### */
/* #                                                                       # */
/* ######################################################################### */
/* #                                                                       # */
/* # Name             : start_kthread                                      # */
/* #                                                                       # */
/* # Description      : Create a new kernel thread. Called by the creator. # */
/* #                                                                       # */
/* # Input Parameters : void (*func)(kthread_t *)                          # */
/* #                    kthread_t *kthread                                 # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          : Public                                             # */
/* #                                                                       # */
/* ######################################################################### */
void start_kthread(void (*func)(kthread_t *), kthread_t *kthread) {
  /* initialize the semaphore:
  we start with the semaphore locked. The new kernel
  thread will setup its stuff and unlock it. This
  control flow (the one that creates the thread) blocks
  in the down operation below until the thread has reached
  the up() operation.
  */
  init_MUTEX_LOCKED(&kthread->startstop_sem);

  /* store the function to be executed in the data passed to
     the launcher */
  kthread->function=func;
        
  /* create the new thread my running a task through keventd */

  /* initialize the task queue structure */
  kthread->tq.sync = 0;
  INIT_LIST_HEAD(&kthread->tq.list);
  kthread->tq.routine =  kthread_launcher;
  kthread->tq.data = kthread;

  /* and schedule it for execution */
  schedule_task(&kthread->tq);

  /* wait till it has reached the setup_thread routine */
  down(&kthread->startstop_sem);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Name             : stop_kthread                                       # */
/* #                                                                       # */
/* # Description      : Stop a kernel thread. Called by the removing       # */
/* #                    instance.                                          # */
/* #                                                                       # */
/* # Input Parameters : kthread_t *kthread                                 # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          : Public                                             # */
/* #                                                                       # */
/* ######################################################################### */
void stop_kthread(kthread_t *kthread) {
  if (kthread->thread == NULL) {
    printk("stop_kthread: killing non existing thread!\n");
    return;
  }

  /* this function needs to be protected with the big
  kernel lock (lock_kernel()). The lock must be
  grabbed before changing the terminate
  flag and released after the down() call. */
  lock_kernel();
        
  /* initialize the semaphore. We lock it here, the
  leave_thread call of the thread to be terminated
  will unlock it. As soon as we see the semaphore
  unlocked, we know that the thread has exited.
  */
  init_MUTEX_LOCKED(&kthread->startstop_sem);

  /* We need to do a memory barrier here to be sure that
  the flags are visible on all CPUs. 
  */
  mb();

  /* set flag to request thread termination */
  kthread->terminate = 1;

  /* We need to do a memory barrier here to be sure that
  the flags are visible on all CPUs. 
  */
  mb();
  kill_proc(kthread->thread->pid, SIGKILL, 1);
       
  /* block till thread terminated */
  down(&kthread->startstop_sem);

  /* release the big kernel lock */
  unlock_kernel();

  /* now we are sure the thread is in zombie state. We
  notify keventd to clean the process up.
  */
  kill_proc(2, SIGCHLD, 1);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Name             : init_kthread                                       # */
/* #                                                                       # */
/* # Description      : Initialize new created thread. Called by the new   # */
/* #                    thread.                                            # */
/* #                                                                       # */
/* # Input Parameters : kthread_t *kthread                                 # */
/* #                    char *name                                         # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          : Public                                             # */
/* #                                                                       # */
/* ######################################################################### */
void init_kthread(kthread_t *kthread, char *name) {
  /* lock the kernel. A new kernel thread starts without
     the big kernel lock, regardless of the lock state
     of the creator (the lock level is *not* inheritated)
  */
  lock_kernel();

  /* fill in thread structure */
  kthread->thread = current;

  /* set signal mask to what we want to respond */
  siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));

  /* initialise wait queue */
  init_waitqueue_head(&kthread->queue);

  /* initialise termination flag */
  kthread->terminate = 0;

  /* set name of this process (max 15 chars + 0 !) */
  sprintf(current->comm, name);
        
  /* let others run */
  unlock_kernel();

  /* tell the creator that we are ready and let him continue */
  up(&kthread->startstop_sem);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Name             : exit_kthread                                       # */
/* #                                                                       # */
/* # Description      : Cleanup of thread. Called by the exiting thread.   # */
/* #                                                                       # */
/* # Input Parameters : kthread_t *kthread                                 # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          : Public                                             # */
/* #                                                                       # */
/* ######################################################################### */
void exit_kthread(kthread_t *kthread) {
  /* we are terminating */

  /* lock the kernel, the exit will unlock it */
  lock_kernel();
  kthread->thread = NULL;
  mb();

  /* notify the stop_kthread() routine that we are terminating. */
  up(&kthread->startstop_sem);
  /* the kernel_thread that called clone() does a do_exit here. */

  /* there is no race here between execution of the "killer" and real
  termination of the thread (race window between up and do_exit), since both
  the thread and the "killer" function are running with the kernel lock held.
  The kernel lock will be freed after the thread exited, so the code
  is really not executed anymore as soon as the unload functions gets
  the kernel lock back.
  The init process may not have made the cleanup of the process here,
  but the cleanup can be done safely with the module unloaded.
  */
}
/* ######################################################################### */

/* ######################################################################### */
/* ######################################################################### */
/* ######################################################################### */





/* ######################################################################### */
/* #                                                                       # */
/* # Name             : KernelThread                                       # */
/* #                                                                       # */
/* # Description      : KernelThread                                       # */
/* #                                                                       # */
/* # Input Parameters : kthread_t *kthread                                 # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          :                                                    # */
/* #                                                                       # */
/* ######################################################################### */
static void KernelThread(kthread_t *kthread) {
  init_kthread(kthread, "Kernel Thread"); /* setup the thread env */
  for(;;) { 
    /* an endless loop in which we are doing our work */

    /* fall asleep for one 10ms */
    interruptible_sleep_on_timeout(&kthread->queue,HZ);

    /* We need to do a memory barrier here to be sure that
    the flags are visible on all CPUs.  */
    mb();
    /* here we are back from sleep, either due to the timeout
    (one 1/100 second), or because we caught a signal.  */
    if(kthread->terminate) { /* we received a request to terminate ourself */
      break;    
    }
    printk("Module: %s: Timeout %d .\n",MODULE_NAME,current->pid);

  } /* Idefinite for loop */
  printk("Module: %s: Kernel Thread Exited.\n",MODULE_NAME);
  /* here we go only in case of termination of the thread */
  /* cleanup the thread, leave */
  exit_kthread(kthread);
  /* returning from the thread here calls the exit functions */
  return;
}
/* ######################################################################### */



/* ######################################################################### */
/* #                                                                       # */
/* # Name             : kt_open                                            # */
/* #                                                                       # */
/* # Description      : Open callback function.                            # */
/* #                                                                       # */
/* # Input Parameters : struct inode *inode                                # */
/* #                    struct file *file                                  # */
/* #                                                                       # */
/* # Result           : int                                                # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          :                                                    # */
/* #                                                                       # */
/* ######################################################################### */
static int kt_open(struct inode *inode,struct file *file) {
  printk("Module: %s: Opened by PID %d.\n",MODULE_NAME,current->pid);
  return(0);
}
/* ######################################################################### */


                                                                                
/* ######################################################################### */
/* #                                                                       # */
/* # Name             : kt_close                                           # */
/* #                                                                       # */
/* # Description      : Close callback function.                           # */
/* #                                                                       # */
/* # Input Parameters : struct inode *inode                                # */
/* #                    struct file *file                                  # */
/* #                                                                       # */
/* # Result           : int                                                # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          :                                                    # */
/* #                                                                       # */
/* ######################################################################### */
static int kt_close(struct inode *inode,struct file *file) {
  printk("Module: %s: Closed by PID %d.\n",MODULE_NAME,current->pid);
  return(0);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Name             : kt_init_module                                     # */
/* #                                                                       # */
/* # Description      : Init callback function.                            # */
/* #                                                                       # */
/* # Input Parameters : void                                               # */
/* #                                                                       # */
/* # Result           : int                                                # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          :                                                    # */
/* #                                                                       # */
/* ######################################################################### */

/* ######################################################################### */
/* # File Operations Structure                                             # */
/* ######################################################################### */
struct file_operations module_fops={
   .owner   =THIS_MODULE,
   .llseek  =NULL,
   .read    =NULL,
   .write   =NULL,
   .readdir =NULL,
   .poll    =NULL,
   .ioctl   =NULL,
   .mmap    =NULL,
   .open    =kt_open,
   .flush   =NULL,
   .release =kt_close,
   .fsync   =NULL,
   .fasync  =NULL,
   .lock    =NULL,
   .readv   =NULL,
   .writev  =NULL,
};
/* ######################################################################### */

/* ######################################################################### */
static int __init kt_init_module (void) {
  int
     result;

  printk("Module: %s: Initializing...\n",MODULE_NAME);
  result=register_chrdev(MODULE_MAJOR,MODULE_NAME,&module_fops);
  if(result!=0)
    return(-EIO);
  start_kthread(KernelThread,&KernelThreadStruct);
  printk("Module: %s: Initialized.\n",MODULE_NAME);
  return(0);
}
/* ######################################################################### */


/* ######################################################################### */
/* #                                                                       # */
/* # Name             : kp_cleanup_module                                  # */
/* #                                                                       # */
/* # Description      : Exit callback function.                            # */
/* #                                                                       # */
/* # Input Parameters : void                                               # */
/* #                                                                       # */
/* # Result           : void                                               # */
/* #                                                                       # */
/* # Revision         : 1.0                                                # */
/* #                                                                       # */
/* # Remarks          :                                                    # */
/* #                                                                       # */
/* ######################################################################### */
static void __exit kt_cleanup_module (void) {
  printk("Module: %s: Cleaning up %d ...\n",MODULE_NAME,current->pid);
  unregister_chrdev(MODULE_MAJOR,MODULE_NAME);
  stop_kthread(&KernelThreadStruct);
  printk("Module: %s: Celaned up.\n",MODULE_NAME);
  return;
}
/* ######################################################################### */

                                                                                
/* ######################################################################### */
/* #                                                                       # */
/* # Module settings                                                       # */
/* #                                                                       # */
/* ######################################################################### */
module_init(kt_init_module);
module_exit(kt_cleanup_module);
MODULE_AUTHOR("From Net");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Kernel Thread");
/* ######################################################################### */
/* ######################################################################### */
/* ######################################################################### */
