alpha: down_interruptible() won't wake up

Kenneth Preslan (kpreslan@zarniwoop.com)
Tue, 16 Mar 1999 04:44:47 -0600 (EST)


I'm having a problem with semaphores on a LX164 Alpha with 2.2.3.

I'm trying use semaphores to wake up a kernel thread. When the thread first
starts, it does a down_interruptible() on a semaphore. The thread sleeps until
another part of my kernel code does an up() on that semaphore. The thread then
does some work and then sleeps on the semaphore again.

At least that's how it's supposed to work. My problem is that on the Alpha,
the thread never wakes up. If I run the code on an i686 (again with 2.2.3)
the thread wakes up. If I change the down_interruptible() to a down()
(on the alpha), the thread wakes up. This leads me to believe that something's
wrong with down_interruptible().

Test case (module):

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
char kernel_version [] = UTS_RELEASE;

#include <linux/locks.h>
#include <linux/smp_lock.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>

struct mydata
{
struct semaphore comm_sema, work_sema;
struct task_struct *thread;
};

static int gfs_inoded(void *data)
{
struct mydata *md = (struct mydata *)data;

printk("thread: In the thread\n");

/* Set up the thread */

lock_kernel();

exit_mm(current);

current->session = 1;
current->pgrp = 1;

siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
current->fs->umask = 0;

sprintf(current->comm, "gfs_inoded");

md->thread = current;

unlock_kernel();

/* Wake up the process who started us */

up(&md->comm_sema);

while (1)
{
printk("thread: before down_interruptible(): counter = %d\n", md->work_sema.count.counter);
down_interruptible(&md->work_sema);
printk("thread: after down_interruptible(): counter = %d\n", md->work_sema.count.counter);

if (signal_pending(current))
{
printk("thread: Thread received signal\n");
break;
}

printk("thread: Doing work...\n");
}

md->thread = NULL;

up(&md->comm_sema);

printk("thread: Leaving the thread\n");

return(0);
}

int init_module(void)
{
struct mydata md;

printk("init: Started init_module...\n");

md.comm_sema = MUTEX_LOCKED;
md.work_sema = MUTEX_LOCKED;

printk("init: Starting thread...\n");

if (kernel_thread(gfs_inoded, &md, 0) < 0)
return(-EIO);

printk("init: Thread started. Waiting for semaphore...\n");

down(&md.comm_sema);

printk("init: The thread is up\n");

printk("init: Telling the thread to do work...\n");

printk("init: before up(): counter = %d\n", md.work_sema.count.counter);
up(&md.work_sema);
printk("init: after up(): counter = %d\n", md.work_sema.count.counter);

printk("init: Sleeping for 10...\n");
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(10 * HZ);

printk("init: Telling the thread to do more work...\n");

printk("init: before up(): counter = %d\n", md.work_sema.count.counter);
up(&md.work_sema);
printk("init: after up(): counter = %d\n", md.work_sema.count.counter);

printk("init: Sleeping for 10...\n");
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(10 * HZ);

printk("init: Sending signal to stop thread\n");

send_sig(SIGKILL, md.thread, 1);

down(&md.comm_sema);

printk("init: exiting...\n");

return(-EIO);
}

Compiled on a i686 with "cc -D__KERNEL__ -DMODULE -Wall -O2 -c test.c",
it does the right thing:

init: Started init_module...
init: Starting thread...
thread: In the thread
thread: before down_interruptible(): counter = 0
init: Thread started. Waiting for semaphore...
init: The thread is up
init: Telling the thread to do work...
init: before up(): counter = -1
init: after up(): counter = 0
init: Sleeping for 10...
thread: after down_interruptible(): counter = 0
thread: Doing work...
thread: before down_interruptible(): counter = 0
<10 second delay>
init: Telling the thread to do more work...
init: before up(): counter = -1
init: after up(): counter = 0
init: Sleeping for 10...
thread: after down_interruptible(): counter = 0
thread: Doing work...
thread: before down_interruptible(): counter = 0
<10 second delay>
init: Sending signal to stop thread
thread: after down_interruptible(): counter = 0
thread: Thread received signal
thread: Leaving the thread
init: exiting...

Compiled on a LX164 Alpha with "cc -D__KERNEL__ -DMODULE -Wall -O2 -mno-fp-regs
-ffixed-8 -Wa,-m21164a -DBWIO_ENABLED -mcpu=ev56 -c test.c", the thread never
wakes up, even though the counter gets incremented:

init: Started init_module...
init: Starting thread...
init: Thread started. Waiting for semaphore...
thread: In the thread
thread: before down_interruptible(): counter = 0
init: The thread is up
init: Telling the thread to do work...
init: before up(): counter = -1
init: after up(): counter = 0
init: Sleeping for 10...
<10 second delay, but the thread doesn't wake up>
init: Telling the thread to do more work...
init: before up(): counter = 0
init: after up(): counter = 1
init: Sleeping for 10...
<10 second delay, but the thread doesn't wake up>
init: Sending signal to stop thread
thread: after down_interruptible(): counter = 2
thread: Thread received signal
thread: Leaving the thread
init: exiting...

Notice that the two down() calls work correctly, but the down_interruptible()
calls don't.

Thanks for your help,

Ken

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/