Re: SMP image on a UP machine

From: Richard B. Johnson
Date: Wed Sep 03 2003 - 12:40:57 EST


On Wed, 3 Sep 2003, Masoodur Rahman wrote:

> Hi ,
>
> Can I run a SMP kernel on a UP machine (x86 based ) ??
>

Yes!

> I am working with 2.4.19 kernel compiled with CONFIG_SMP on a
> UniProcessor machine. The machine boots up with the SMP kernel
> configured in .
>

Fine.

> The Problem comes when I try to create a kernel thread using
> the example at http://www.scs.ch/~frey/linux/kernelthreads.html
>
> The entire machine hangs on loading the thread_mod.o ..
>
> What am I doing wrong ?? Is there any option that needs to be
> turned on to get this working ??
>

Kernel threads, properly implemented, do not hang the machine, SMP
or not. Find some other source to copy. The attached file, written
by Vladmir Kondratiev of Intel works.


Cheers,
Dick Johnson
Penguin : Linux version 2.4.22 on an i686 machine (794.73 BogoMips).
Note 96.31% of all statistics are fiction.

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>

typedef struct kt_priv_struct {
int nthreads; /**< let's count how many times kernel_thread succeeded */
int pid;
wait_queue_head_t wq; /**< kthread sleep here */
struct completion exited;
__u32 volatile status;
} kt_priv_t;

static kt_priv_t the_data;

static int kt_thread(void* arg)
{
kt_priv_t* priv=(kt_priv_t*)arg;
daemonize();
reparent_to_init();
snprintf(current->comm,sizeof(current->comm),"kth_%d",priv->nthreads);
++priv->nthreads;
while (!test_bit(0,&priv->status)) {
/* framework for periodical execution */
unsigned long to=HZ; /* timeout for periodical maintenance */
do {
to=interruptible_sleep_on_timeout(&priv->wq,to);
} while ( !signal_pending(current) && to>0 );
if (signal_pending(current)) {
spin_lock_irq(&current->sigmask_lock);
flush_signals(current);
spin_unlock_irq(&current->sigmask_lock);
}
/* thread body - for this simple example do nothing */
}
complete_and_exit(&priv->exited,0);
}

static void kt_start(kt_priv_t* priv)
{
if (priv->pid>0) return;
init_completion(&priv->exited);
init_waitqueue_head(&priv->wq);
priv->status=0;
priv->pid=kernel_thread(kt_thread,priv,0);
}

static void kt_stop(kt_priv_t* priv)
{
if (priv->pid>0 && (0==test_and_set_bit(0,&priv->status))) {
kill_proc(priv->pid,SIGHUP,1);
wait_for_completion(&priv->exited);
priv->pid=0;
}
}

static int kt_proc_read(char* buf,char** start,off_t offset,int
count,int* eof,void* data)
{
kt_priv_t* priv=(kt_priv_t*)data;
int len=0;
len+=sprintf(buf+len,"nthreads = %d\n",priv->nthreads);
len+=sprintf(buf+len,"pid = %d\n",priv->pid);
*eof=1;
return len;
}

static int kt_proc_write(struct file *file, const char *buffer, unsigned
long count, void *data)
{
char *buf;
kt_priv_t* priv=(kt_priv_t*)data;
int rc = count;
if (count<1)
{
return -EINVAL;
}
buf = vmalloc(count+1);
if (!buf) return -ENOMEM;
buf[count]='\0';
if (copy_from_user(buf,buffer,count))
{
rc=-EFAULT;
goto out;
}
switch (buf[0])
{
case '+':
kt_start(priv);
break;
case '-':
kt_stop(priv);
break;
}
out:
vfree(buf);
return rc;
}

static char* kt_proc_name="kthread";

static int kt_mod_init(void)
{
struct proc_dir_entry *p;
kt_priv_t* priv=&the_data;
memset(priv,0,sizeof(*priv));
p=create_proc_read_entry(kt_proc_name,0666,NULL,kt_proc_read,priv);
if (p) {
SET_MODULE_OWNER(p);
p->write_proc=kt_proc_write;
}
return 0;
}

static void kt_mod_exit(void)
{
kt_stop(&the_data);
remove_proc_entry(kt_proc_name,NULL);
}

module_init(kt_mod_init);
module_exit(kt_mod_exit);

MODULE_AUTHOR("Vladimir Kondratiev <vladimir.kondratiev@xxxxxxxxx>");
MODULE_DESCRIPTION("Kernel thread example");
MODULE_LICENSE("GPL");