2001-03-23 12:08:31

by Stelian Pop

[permalink] [raw]
Subject: Use semaphore for producer/consumer case...

Hi,

I want to use a semaphore for the classic producer/consumer case
(put the consumer to wait until X items are produced, where X != 1).

If X is 1, the semaphore is a simple MUTEX, ok.

But if the consumer wants to wait for several items, it doesn't
seem to work (or something is bad in my code).

What is wrong in the following ?

DECLARE_MUTEX(sem);

producer() {
/* One item produced */
up(&sem);
}

consumer() {
/* Let's wait for 10 items */
atomic_set(&sem->count, -10);

/* This starts the producers, they will call producer()
some time in the future */
start_producers();

/* Wait for completion */
down(&sem);
}

I can get around this by using a mutex and a separate atomic_t
'count' variable, but it's more a workaround that a solution...

Thanks,

Stelian.
--
Stelian Pop <[email protected]>
|------------- Ing?nieur Informatique Libre --------------|
| Alc?ve - http://www.alcove.com - Tel: +33 1 49 22 68 00 |
|----------- Alc?ve, l'informatique est libre ------------|


2001-03-23 18:35:30

by Manfred Spraul

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

> consumer()

> /* Let's wait for 10 items */
> atomic_set(&sem->count, -10);

That doesn't work, at least the i386 semaphore implementation doesn't
support semaphore counts < 0.

--
Manfred

2001-03-23 23:54:07

by Nigel Gamble

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

On Fri, 23 Mar 2001, Stelian Pop wrote:
> I want to use a semaphore for the classic producer/consumer case
> (put the consumer to wait until X items are produced, where X != 1).
>
> If X is 1, the semaphore is a simple MUTEX, ok.
>
> But if the consumer wants to wait for several items, it doesn't
> seem to work (or something is bad in my code).
>
> What is wrong in the following ?
>
> DECLARE_MUTEX(sem);

For the producer/consumer case, you want to initialize the semaphore to
0, not 1 which DECLARE_MUTEX(sem) does. So I would use

__DECLARE_SEMAPHORE_GENERIC(sem, 0)

The count is then the number of items produced but not yet consumed.

> producer() {
> /* One item produced */
> up(&sem);
> }
>
> consumer() {
> /* Let's wait for 10 items */
> atomic_set(&sem->count, -10);
>
> /* This starts the producers, they will call producer()
> some time in the future */
> start_producers();
>
> /* Wait for completion */
> down(&sem);
> }

Then consumer could be:

consumer()
{
int i;

start_producers();

/* Wait for 10 items to be produced */
for (i = 0; i < 10; i++)
down(&sem);
}


Nigel Gamble [email protected]
Mountain View, CA, USA. http://www.nrg.org/

MontaVista Software [email protected]

2001-03-26 14:55:31

by Stelian Pop

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

On Fri, Mar 23, 2001 at 07:34:07PM +0100, Manfred Spraul wrote:
> > consumer()
>
> > /* Let's wait for 10 items */
> > atomic_set(&sem->count, -10);
>
> That doesn't work, at least the i386 semaphore implementation doesn't
> support semaphore counts < 0.

Does that mean that kernel semaphore can not be used for something
else than mutual exclusion ?

Stelian.
--
Stelian Pop <[email protected]>
|------------- Ing?nieur Informatique Libre --------------|
| Alc?ve - http://www.alcove.com - Tel: +33 1 49 22 68 00 |
|----------- Alc?ve, l'informatique est libre ------------|

2001-03-26 14:54:21

by Stelian Pop

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

On Fri, Mar 23, 2001 at 03:52:54PM -0800, Nigel Gamble wrote:

> For the producer/consumer case, you want to initialize the semaphore to
> 0, not 1 which DECLARE_MUTEX(sem) does. So I would use
>
> __DECLARE_SEMAPHORE_GENERIC(sem, 0)

You're right that the DECLARE_MUTEX does not (entirely) do the job,
but I set manually the value of sem->count:
> > atomic_set(&sem->count, -10);

> Then consumer could be:
> /* Wait for 10 items to be produced */
> for (i = 0; i < 10; i++)
> down(&sem);

IMHO, this will not work, because the producer could be issuing
more than one 'up(&sem)' at the time...

Stelian.
--
Stelian Pop <[email protected]>
|------------- Ing?nieur Informatique Libre --------------|
| Alc?ve - http://www.alcove.com - Tel: +33 1 49 22 68 00 |
|----------- Alc?ve, l'informatique est libre ------------|

2001-03-26 17:14:03

by Manfred Spraul

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

From: "Stelian Pop" <[email protected]>
> >
> > That doesn't work, at least the i386 semaphore implementation
doesn't
> > support semaphore counts < 0.
>
> Does that mean that kernel semaphore can not be used for something
> else than mutual exclusion ?
>
It's a bit better: counts >= 0 are supported, i.e. you can call up()
before down(), and that's used in several places.

The for loop that Nigel proposed should solve your problem. Multiple
up's are handled correctly.

--
Manfred

2001-03-27 07:58:14

by Stelian Pop

[permalink] [raw]
Subject: Re: Use semaphore for producer/consumer case...

On Mon, Mar 26, 2001 at 07:12:55PM +0200, Manfred Spraul wrote:

> > > That doesn't work, at least the i386 semaphore implementation
> doesn't
> > > support semaphore counts < 0.
> >
> > Does that mean that kernel semaphore can not be used for something
> > else than mutual exclusion ?
> >
> It's a bit better: counts >= 0 are supported, i.e. you can call up()
> before down(), and that's used in several places.

I see... it's somewhat different than the classical semaphore
implementation, but usable anyway.

> The for loop that Nigel proposed should solve your problem. Multiple
> up's are handled correctly.

Now I understand his suggestion. Thanks to both of you.

Stelian.
--
Stelian Pop <[email protected]>
|------------- Ing?nieur Informatique Libre --------------|
| Alc?ve - http://www.alcove.com - Tel: +33 1 49 22 68 00 |
|----------- Alc?ve, l'informatique est libre ------------|