00001 #include <linux/types.h>
00002 #include <linux/kernel.h>
00003 #include <linux/ioctl.h>
00004 #include <linux/module.h>
00005 #include <linux/init.h>
00006 #include <linux/errno.h>
00007 #include <linux/mm.h>
00008 #include <linux/devfs_fs_kernel.h>
00009 #include <linux/mmtimer.h>
00010 #include <linux/miscdevice.h>
00011 #include <linux/posix-timers.h>
00012 #include <linux/interrupt.h>
00013 #include <linux/config.h>
00014 #include <linux/module.h>
00015 #include <linux/kernel.h>
00016 #include <linux/spinlock.h>
00017
00018 #include <linux/aquosa/qos_debug.h>
00019
00020 pid_t timer_thread_pid;
00021 struct task_struct *p_timer_thread_ts = 0;
00022
00023 extern int force_ksoftirqd;
00024
00025 struct k_itimer timer;
00026
00027 struct itimerspec its = {
00028 .it_interval = {
00029 .tv_sec = 0,
00030 .tv_nsec = 100000000
00031 },
00032 .it_value = {
00033 .tv_sec = 0,
00034 .tv_nsec = 100000000
00035 }
00036 };
00037
00038 struct itimerval itv = {
00039 .it_interval = {
00040 .tv_sec = 0,
00041 .tv_usec = 100000
00042 },
00043 .it_value = {
00044 .tv_sec = 0,
00045 .tv_usec = 100000
00046 }
00047 };
00048
00049 int timer_thread(void *_c)
00050 {
00051 int rv;
00052 unsigned long flags;
00053
00054 p_timer_thread_ts = current;
00055
00056 qos_log_crit("timer_thread(): Daemonizing timer thread (pid=%d)", (int)current->pid);
00057 daemonize("timer");
00058 qos_log_crit("timer_thread(): Allowing signals");
00059 allow_signal(SIGKILL);
00060 allow_signal(SIGSTOP);
00061 allow_signal(SIGCONT);
00062 allow_signal(SIGALRM);
00063
00064 qos_log_crit("timer_thread(): forcing execution of softirqs outside interrupt context");
00065 force_ksoftirqd = 1;
00066
00067 rv = do_setitimer(ITIMER_REAL, &itv, NULL);
00068 qos_log_crit("timer_thread(): do_setitimer() returned: %d", rv);
00069 if (rv != 0)
00070 goto die;
00071 spin_lock_init(&timer.it_lock);
00072 spin_lock_irqsave(&timer.it_lock, flags);
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 do {
00100 siginfo_t info;
00101 unsigned long signr;
00102
00103 while (! signal_pending(current)) {
00104 qos_log_crit("timer_thread(): Waiting signal...");
00105 set_current_state(TASK_INTERRUPTIBLE);
00106 spin_unlock_irqrestore(&timer.it_lock, flags);
00107 schedule();
00108 spin_lock_irqsave(&timer.it_lock, flags);
00109 }
00110
00111 spin_unlock_irqrestore(&timer.it_lock, flags);
00112
00113 qos_log_crit("timer_thread(): Dequeuing signal");
00114 signr = dequeue_signal_lock(current, ¤t->blocked, &info);
00115 qos_log_crit("timer_thread(): Dequeued signal: %lu", signr);
00116
00117 switch(signr) {
00118 case SIGSTOP:
00119 qos_log_crit("timer_thread(): SIGSTOP received.");
00120 set_current_state(TASK_STOPPED);
00121 schedule();
00122 break;
00123
00124 case SIGKILL:
00125 qos_log_crit("timer_thread(): SIGKILL received.");
00126 goto die;
00127
00128 case SIGHUP:
00129 qos_log_crit("timer_thread(): SIGHUP received.");
00130 break;
00131
00132 case SIGALRM:
00133 qos_log_crit("timer_thread(): SIGALARM received: %lu", jiffies);
00134 break;
00135
00136 default:
00137 qos_log_crit("timer_thread(): signal %ld received", signr);
00138 }
00139 spin_lock_irqsave(&timer.it_lock, flags);
00140 } while (1);
00141
00142 qos_log_crit("timer_thread(): Ended while loop");
00143
00144 die:
00145
00146 qos_log_crit("timer_thread(): unforcing execution of softirqs outside interrupt context");
00147 force_ksoftirqd = 0;
00148
00149 qos_log_crit("timer_thread(): Exiting");
00150 }
00151
00152 void start_timer_thread(void)
00153 {
00154 int ret = 0;
00155
00156 qos_log_crit("Starting timer thread");
00157 timer_thread_pid = kernel_thread(timer_thread, NULL, CLONE_KERNEL);
00158 if (timer_thread_pid < 0) {
00159 qos_log_crit("fork failed for timer thread: %d", -timer_thread_pid);
00160 }
00161 qos_log_crit("Timer thread started");
00162 }
00163
00164 void stop_timer_thread(void)
00165 {
00166 qos_log_crit("Stopping timer thread");
00167 if (p_timer_thread_ts)
00168 send_sig(SIGKILL, p_timer_thread_ts, 1);
00169 qos_log_crit("Timer thread stopped");
00170 }