All of lore.kernel.org
 help / color / mirror / Atom feed
* Athlon PSE/AGP Bug
From: Ben Carrell @ 2002-01-22 17:59 UTC (permalink / raw)
  To: linux-kernel

Just curious if using 4k page tables versus 4mb has an effect on
performance?

-Ben Carrell
ben@xmission.com

^ permalink raw reply

* Re: [PATCH][RFC] AMD Elan patch
From: Dave Jones @ 2002-01-22 18:01 UTC (permalink / raw)
  To: Robert Schwebel; +Cc: Linux Kernel List
In-Reply-To: <Pine.LNX.4.33.0201221545350.21377-100000@callisto.local>

On Tue, Jan 22, 2002 at 03:47:32PM +0100, Robert Schwebel wrote:
 > 
 > I have another patch from Sven Geggus in the pipeline which makes it
 > possible to change the CPU's clock frequency on the fly.

 It would probably be a good idea to make this fit the cpufreq
 API that Russell King, myself and a few others created.
 It's in the ARM Linux CVS with the modulename cpufreq.

-- 
| Dave Jones.        http://www.codemonkey.org.uk
| SuSE Labs

^ permalink raw reply

* Re: [parisc-linux] vmlinux header for savecrash.
From: Bruno Vidal @ 2002-01-22 17:59 UTC (permalink / raw)
  To: Randolph Chung; +Cc: parisc-linux@lists.parisc-linux.org
In-Reply-To: <20020122175332.GF3247@tausq.org>

[-- Attachment #1: Type: text/plain, Size: 769 bytes --]

lkcd is really simple, it takes /boot/vmlinux, /boot/kerntype, 
and /boot/System.map. It don't take care about that, it is the 
user problem :-(, I want to be a little more user friendly.

Randolph Chung wrote:
> 
> > Randolph Chung and I were wondering if dump driver could save a
> > parameter passed in by palo: eg "boot_kernel=/boot/vmlinux-pa11".
> > I haven't checked if something like that already exists.
> 
> Is this really an arch-dependent problem? How do other architectures (I
> think lkcd works on i386 and alpha?) do this?
> 
> randolph
> --
>    @..@                                         http://www.TauSq.org/
>   (----)
>  ( >__< )
>  ^^ ~~ ^^

-- 
	Vidal Bruno, (770-4271)
        SSD-HA Team, HP-UX & LINUX Support
	bruno_vidal@admin.france.hp.com

[-- Attachment #2: Card for Bruno Vidal --]
[-- Type: text/x-vcard, Size: 386 bytes --]

begin:vcard 
n:Bruno;VIDAL
tel;fax:01-69-82-60-14
tel;work:01-69-29-42-71
x-mozilla-html:TRUE
url:www.france.hp.com
org:Solution Center
version:2.1
email;internet:bruno_vidal@hp.com
title:Expert Logiciel Environnement Haute Disponibilité
adr;quoted-printable:;;HP France=0D=0A;Z.A de Courtaboeuf;1 Av. du Canada;91947 Les Ulis cedex;France
x-mozilla-cpt:;26208
fn:VIDAL Bruno
end:vcard

^ permalink raw reply

* metadata and contents in loop device
From: Michael Zhu @ 2002-01-22 18:02 UTC (permalink / raw)
  To: linux-crypto; +Cc: linux-kernel

Hello, everyone, in my loop device I want to use
different keys to en/decrypt the file contents and the
metadata of directories/file names information. But
how can I differentiate these two types of data in the
loop device? The loop device just cares about the
block. But the metadata of directories/file names
information is just the file system information. Any
idea about this? Thanks in advance.

Michael

______________________________________________________________________ 
Web-hosting solutions for home and business! http://website.yahoo.ca

^ permalink raw reply

* Re: [patch] VAIO irq assignment fix ->CompactFlash-pcmcia freeze
From: root @ 2002-01-22 18:01 UTC (permalink / raw)
  To: linux; +Cc: linux-kernel
In-Reply-To: <000c01c1a2ad$efc5bcc0$8119fea9@lee>

[-- Attachment #1: Type: text/plain, Size: 5052 bytes --]

Lee Packham wrote:

> One is a wireless card, one is a compact flash converter thing (for the
> camera).
>
> Both cards work individually. The laptop locks up if I insert both
> cards. There is no OOPS or anything... It just locks up. Removing the
> cards does not spring it back to life.
>
> It is probably down to the fact that the Vaio laptops assign everything
> IRQ9. Please find attached my /proc/interrupts and lspci -vvv.

This is _probably_ caused by an IRQ storm, as the IDE code (which is
used for your Compact Flash) raises an IRQ in it's probe routine
but hasn't installed a handler.

The proper patch for this is ignored by Linus and Marcelo since August 2000.

Though Andre has acknowledged the bug and my patch is included in
his latest ide patches.

Try this and report:

diff -ur linux-2.4.15.orig/drivers/ide/ide-cs.c linux/drivers/ide/ide-cs.c
--- linux-2.4.15.orig/drivers/ide/ide-cs.c      Sun Sep 30 21:26:05 2001
+++ linux/drivers/ide/ide-cs.c  Sun Nov 25 13:11:36 2001
@@ -42,6 +42,7 @@
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
 #include <linux/major.h>
+#include <linux/ide.h>

 #include <asm/io.h>
 #include <asm/system.h>
@@ -226,6 +227,16 @@
 #define CFG_CHECK(fn, args...) \
 if (CardServices(fn, args) != 0) goto next_entry

+int idecs_register (int io_base, int ctl_base, int irq)
+{
+        hw_regs_t hw;
+        ide_init_hwif_ports(&hw, (ide_ioreg_t) io_base, (ide_ioreg_t)
ctl_base, NULL);
+        hw.irq = irq;
+        hw.chipset = ide_pci; // this enables IRQ sharing w/ PCI irqs
+        return ide_register_hw(&hw, NULL);
+}
+
+
 void ide_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
@@ -327,12 +338,16 @@
     if (link->io.NumPorts2)
        release_region(link->io.BasePort2, link->io.NumPorts2);

+    /* disable drive interrupts during IDE probe */
+    if(ctl_base)
+       outb(0x02, ctl_base);
+
     /* retry registration in case device is still spinning up */
     for (i = 0; i < 10; i++) {
-       hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ);
+       hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
        if (hd >= 0) break;
        if (link->io.NumPorts1 == 0x20) {
-           hd = ide_register(io_base+0x10, ctl_base+0x10,
+           hd = idecs_register(io_base+0x10, ctl_base+0x10,
                              link->irq.AssignedIRQ);
            if (hd >= 0) {
                io_base += 0x10; ctl_base += 0x10;
Only in linux/drivers/ide: ide-cs.c-2415
diff -ur linux-2.4.15.orig/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.4.15.orig/drivers/ide/ide.c Thu Oct 25 22:58:35 2001
+++ linux/drivers/ide/ide.c     Sun Nov 25 13:02:34 2001
@@ -2293,6 +2293,7 @@
        memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));

        hwif->irq = hw->irq;
        hwif->noprobe = 0;
+       hwif->chipset = hw->chipset;

        if (!initializing) {
                ide_probe_module();
diff -ur linux-2.4.15.orig/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.4.15.orig/include/linux/ide.h       Thu Nov 22 20:48:07 2001
+++ linux/include/linux/ide.h   Sun Nov 25 13:05:57 2001
@@ -223,6 +223,23 @@
 #endif

 /*
+ * hwif_chipset_t is used to keep track of the specific hardware
+ * chipset used by each IDE interface, if known.
+ */
+typedef enum {  ide_unknown,    ide_generic,    ide_pci,
+                ide_cmd640,     ide_dtc2278,    ide_ali14xx,
+                ide_qd65xx,     ide_umc8672,    ide_ht6560b,
+                ide_pdc4030,    ide_rz1000,     ide_trm290,
+                ide_cmd646,     ide_cy82c693,   ide_4drives,
+                ide_pmac,       ide_etrax100
+} hwif_chipset_t;
+
+#define IDE_CHIPSET_PCI_MASK    \
+    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
+#define IDE_CHIPSET_IS_PCI(c)   ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+
+
+/*
  * Structure to hold all information about the location of this port
  */
 typedef struct hw_regs_s {
@@ -231,6 +248,7 @@
        int             dma;                    /* our dma entry */
        ide_ack_intr_t  *ack_intr;              /* acknowledge interrupt */
        void            *priv;                  /* interface specific data */

+       hwif_chipset_t  chipset;
 } hw_regs_t;

 /*
@@ -439,22 +457,6 @@
  * ide soft-power support
  */
 typedef int (ide_busproc_t) (struct hwif_s *, int);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum { ide_unknown,    ide_generic,    ide_pci,
-               ide_cmd640,     ide_dtc2278,    ide_ali14xx,
-               ide_qd65xx,     ide_umc8672,    ide_ht6560b,
-               ide_pdc4030,    ide_rz1000,     ide_trm290,
-               ide_cmd646,     ide_cy82c693,   ide_4drives,
-               ide_pmac,       ide_etrax100
-} hwif_chipset_t;
-
-#define IDE_CHIPSET_PCI_MASK   \
-    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
-#define IDE_CHIPSET_IS_PCI(c)  ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)

 #ifdef CONFIG_BLK_DEV_IDEPCI
 typedef struct ide_pci_devid_s {




[-- Attachment #2: gmdiff-lx2415-compactflash+pcmcia+PCI --]
[-- Type: text/plain, Size: 3930 bytes --]

diff -ur linux-2.4.15.orig/drivers/ide/ide-cs.c linux/drivers/ide/ide-cs.c
--- linux-2.4.15.orig/drivers/ide/ide-cs.c	Sun Sep 30 21:26:05 2001
+++ linux/drivers/ide/ide-cs.c	Sun Nov 25 13:11:36 2001
@@ -42,6 +42,7 @@
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
 #include <linux/major.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -226,6 +227,16 @@
 #define CFG_CHECK(fn, args...) \
 if (CardServices(fn, args) != 0) goto next_entry
 
+int idecs_register (int io_base, int ctl_base, int irq)
+{
+        hw_regs_t hw;
+        ide_init_hwif_ports(&hw, (ide_ioreg_t) io_base, (ide_ioreg_t) ctl_base, NULL);
+        hw.irq = irq;
+        hw.chipset = ide_pci; // this enables IRQ sharing w/ PCI irqs
+        return ide_register_hw(&hw, NULL);
+}
+
+
 void ide_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
@@ -327,12 +338,16 @@
     if (link->io.NumPorts2)
 	release_region(link->io.BasePort2, link->io.NumPorts2);
 
+    /* disable drive interrupts during IDE probe */
+    if(ctl_base)
+    	outb(0x02, ctl_base);
+
     /* retry registration in case device is still spinning up */
     for (i = 0; i < 10; i++) {
-	hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ);
+	hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
 	if (hd >= 0) break;
 	if (link->io.NumPorts1 == 0x20) {
-	    hd = ide_register(io_base+0x10, ctl_base+0x10,
+	    hd = idecs_register(io_base+0x10, ctl_base+0x10,
 			      link->irq.AssignedIRQ);
 	    if (hd >= 0) {
 		io_base += 0x10; ctl_base += 0x10;
Only in linux/drivers/ide: ide-cs.c-2415
diff -ur linux-2.4.15.orig/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.4.15.orig/drivers/ide/ide.c	Thu Oct 25 22:58:35 2001
+++ linux/drivers/ide/ide.c	Sun Nov 25 13:02:34 2001
@@ -2293,6 +2293,7 @@
 	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
 	hwif->irq = hw->irq;
 	hwif->noprobe = 0;
+	hwif->chipset = hw->chipset;
 
 	if (!initializing) {
 		ide_probe_module();
diff -ur linux-2.4.15.orig/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.4.15.orig/include/linux/ide.h	Thu Nov 22 20:48:07 2001
+++ linux/include/linux/ide.h	Sun Nov 25 13:05:57 2001
@@ -223,6 +223,23 @@
 #endif
 
 /*
+ * hwif_chipset_t is used to keep track of the specific hardware
+ * chipset used by each IDE interface, if known.
+ */
+typedef enum {  ide_unknown,    ide_generic,    ide_pci,
+                ide_cmd640,     ide_dtc2278,    ide_ali14xx,
+                ide_qd65xx,     ide_umc8672,    ide_ht6560b,
+                ide_pdc4030,    ide_rz1000,     ide_trm290,
+                ide_cmd646,     ide_cy82c693,   ide_4drives,
+                ide_pmac,       ide_etrax100
+} hwif_chipset_t;
+
+#define IDE_CHIPSET_PCI_MASK    \
+    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
+#define IDE_CHIPSET_IS_PCI(c)   ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+
+
+/*
  * Structure to hold all information about the location of this port
  */
 typedef struct hw_regs_s {
@@ -231,6 +248,7 @@
 	int		dma;			/* our dma entry */
 	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
 	void		*priv;			/* interface specific data */
+	hwif_chipset_t  chipset;
 } hw_regs_t;
 
 /*
@@ -439,22 +457,6 @@
  * ide soft-power support
  */
 typedef int (ide_busproc_t) (struct hwif_s *, int);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum {	ide_unknown,	ide_generic,	ide_pci,
-		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
-		ide_qd65xx,	ide_umc8672,	ide_ht6560b,
-		ide_pdc4030,	ide_rz1000,	ide_trm290,
-		ide_cmd646,	ide_cy82c693,	ide_4drives,
-		ide_pmac,       ide_etrax100
-} hwif_chipset_t;
-
-#define IDE_CHIPSET_PCI_MASK	\
-    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
-#define IDE_CHIPSET_IS_PCI(c)	((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 typedef struct ide_pci_devid_s {

^ permalink raw reply

* RE: Autostart RAID 1+0 (root)
From: Alok K. Dhir @ 2002-01-22 18:07 UTC (permalink / raw)
  To: 'Jakob Østergaard'; +Cc: linux-kernel
In-Reply-To: <20020122184600.C11697@unthought.net>

> > > 
> > > Does the kernel support autostarting nested RAID partitions?
> > > 
> 
> Yes it does.  If you have persistent superblocks on all arrays, they
> *should* autostart.
> 
> If you boot from the 4G disk, does the array start properly ? 
>  Does it start properly even if you remove your /etc/raidtab ?
> 
> Please check that you have the correct RAID levels either 
> compiled into your kernel, or on an initrd.

1.  I have persistent superblocks on all arrays.  
2.  Booting from the 4G does allow the arrays to start properly.
3.  The first two arrays (md0 and md1, the mirrors) start properly
without raidtab.  The third, the stripe between md0 and md1, does not.
4.  All raid levels are compiled as modules, along with reiserfs, and my
scsi card driver in an initrd.  I also tried compiling a monolithic
kernel with all of these without success.

I did, in fact, get it working.  The only way I was able to do boot with
my nested array autostarted and mounted as root was to create an initrd
with a statically compiled raidstart and a copy of my raidtab in the
initrd's etc dir.  I then issue "raidstart mdx" commands for each of the
arrays in linuxrc.  I actually just modified the mkinitrd genereated
initrd image.

I can only conclude that autostarting nested arrays either doesn't work,
or is broken in RH-2.4.9-13.  I have not tried a more recent kernel with
this machine.

Thanks

Al


^ permalink raw reply

* Re: metadata and contents in loop device
From: Alexander Viro @ 2002-01-22 18:07 UTC (permalink / raw)
  To: Michael Zhu; +Cc: linux-crypto, linux-kernel
In-Reply-To: <20020122180201.42898.qmail@web14905.mail.yahoo.com>



On Tue, 22 Jan 2002, Michael Zhu wrote:

> Hello, everyone, in my loop device I want to use
> different keys to en/decrypt the file contents and the
> metadata of directories/file names information. But
> how can I differentiate these two types of data in the
> loop device?

You can't.


^ permalink raw reply

* Re: thread-ready ABIs
From: Kevin D. Kissell @ 2002-01-22 17:08 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Dominic Sweetman, Ralf Baechle, Ulrich Drepper, Mike Uhler,
	MIPS/Linux List (SGI), H . J . Lu
In-Reply-To: <20020122113420.A14284@nevyn.them.org>

> Perhaps I'm mangling terminology.  LinuxThreads is a one-to-one mapping
> of kernel threads to user threads.  All the kernel threads, and thus
> all the user threads, share the same memory region - including the
> stack region.  Their stacks are differentiated solely by different
> values in the stack pointer register.  Thus I don't think what you're
> suggesting is possible.

I don't see how fork() semantics can be preserved unless
the stack regions are replicated (copy-on-write) on a fork().
Under ATT and BSD Unix (which is where I did most of
my kernel hacking in the old days) that was the *only*
way to get a new kernel thread, so it was "obvious"
that my proposed hack would work.  Linux does have
the clone() function as well, and if LinuxThreads are
implemented in terms of clone(foo, stakptr, CLONE_VM, arg),
you are correct, the proposed scheme would not work
without modification.

One such modification would be to have each newly
cloned thread explicitly allocate and map a 1-page
VM region that is private to the kernel thread, and bound 
to a known virtual address that is common to all threads
within the task.  That known virtual address would take the 
place of the below-the-stack storage location I described 
earlier.  The same algorithm would apply - one has a globally 
known address that maps to different storage per-thread, 
which can be used to store the address of the (globally visible) 
per-thread information.  The set-up is slightly more complicated 
and heavyweight than the fork()-based model I suggested, 
but one could in principle eliminate one level of indirection 
at on the lookups at run-time.

            Regards,

            Kevin K.
 

^ permalink raw reply

* Re: [parisc-linux] vmlinux header for savecrash.
From: Randolph Chung @ 2002-01-22 18:11 UTC (permalink / raw)
  To: Bruno Vidal; +Cc: Grant Grundler, parisc-linux@lists.parisc-linux.org
In-Reply-To: <3C4DA793.B17F1D3C@admin.france.hp.com>

In reference to a message from Bruno Vidal, dated Jan 22:
> 	Hi
> I don't know how to retrieve option pass to the kernel,
> but give me some clue, and I'll add this information in
> the dump header asap, because it is a really good idea :-)

static char *boot_kernel = "/boot/vmlinux";
MODULE_PARM(boot_kernel, "s")
MODULE_PARM_DESC(boot_kernel, "Boot kernel path")

then i guess somehwere in your dump code strcpy boot_kernel to a known
location in the dump.

of course we still need to change palo to do this (pass the
parameter)... paul, any comments?

randolph
-- 
   @..@                                         http://www.TauSq.org/
  (----)
 ( >__< )
 ^^ ~~ ^^

^ permalink raw reply

* Re: thread-ready ABIs
From: Daniel Jacobowitz @ 2002-01-22 17:13 UTC (permalink / raw)
  To: Kevin D. Kissell
  Cc: Dominic Sweetman, Ralf Baechle, Ulrich Drepper, Mike Uhler,
	MIPS/Linux List (SGI), H . J . Lu
In-Reply-To: <00c001c1a367$69c10160$0deca8c0@Ulysses>

On Tue, Jan 22, 2002 at 06:08:12PM +0100, Kevin D. Kissell wrote:
> > Perhaps I'm mangling terminology.  LinuxThreads is a one-to-one mapping
> > of kernel threads to user threads.  All the kernel threads, and thus
> > all the user threads, share the same memory region - including the
> > stack region.  Their stacks are differentiated solely by different
> > values in the stack pointer register.  Thus I don't think what you're
> > suggesting is possible.
> 
> I don't see how fork() semantics can be preserved unless
> the stack regions are replicated (copy-on-write) on a fork().
> Under ATT and BSD Unix (which is where I did most of
> my kernel hacking in the old days) that was the *only*
> way to get a new kernel thread, so it was "obvious"
> that my proposed hack would work.  Linux does have
> the clone() function as well, and if LinuxThreads are
> implemented in terms of clone(foo, stakptr, CLONE_VM, arg),
> you are correct, the proposed scheme would not work
> without modification.

Which it is.  Fork shares no memory regions; vfork/clone share all
memory regions.  AFAIK there is no share-heap-but-not-stack option in
Linux.

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer

^ permalink raw reply

* Re: patches for test-and-set without ll/sc (Re: thread-ready ABIs)
From: Kevin D. Kissell @ 2002-01-22 17:16 UTC (permalink / raw)
  To: aj, hjl, ralf, Machida Hiroyuki; +Cc: linux-mips
In-Reply-To: <20020122232529V.machida@sm.sony.co.jp>

> Kevin, please let us  know about "k1 semaphore" you said.
> I want to know we can merge those functions or not.

My proposal is for a very simple emulation of ll/sc for
CPUs that implement the MIPS II "branch likely" instructions
but which do not have a functioning LL/SC. That means
that it is *not* a solution for R3000 processor such as
those found in old DEC and SGI platforms.  LL/SC is
also part of MIPS II, but several manufacturers seem
to have done MIPS II/III processors where LL/SC
is not fully functional.  This hack could thus be workable
both for the TX59 family and the Vr4100 family.

The idea leverages off the fact that a branch likely
instruction performs a kind of conditional execution.
The instruction in the delay slot is executed only if
the branch is taken.  This can be used to synthesize
a conditional store.  The user level code for a simple
atomic increment, for example, would look something
like this:

_atomic_inc_nollsc:
        .set  noreorder
        li    t0,MAGIC_COOKIE
Retry:
        mov      k1,t0
        lw         t1,0(a0)
        addiu    t1,t1,1
        BEQL  k1,t0,done
        sw        t1,0(a0)
        b          Retry
        nop
done
        jr        ra
        nop
 
If - and this is an important consideration - IF the value
of MAGIC_COOKIE can be determined such that
it can *never* be the residue value left in k1 by a
kernel exception handler, *no* kernel modifications
are required for this to work identically to LL/SC!
If, for example, k1 always ends up containing either
a Status, EPC, or EntryLo value after an ERET, something
like 0xffdadaff could be used as a MAGIC_COOKIE
value, as it is not a sane value for any of the above.

You will get some number of needless retries
in this scheme to the extent that there are TLB
misses on the load and on the instructions themselves
if the routine crosses a page boundary.  You
would get those same retries using LL/SC.
You could eliminate those retries by preserving
the appropriate k-register in the TLB refill handler,
but I really doubt that it would be worthwhile.

If there is any doubt about the possibility of the
MAGIC_COOKIE value being left in k1 (or
k0, which could also be used as the "LL flop"
if its behavior is more easily constrained), an
explicit operation at the end of the fault handlers
could be used to clear the register.  That would
still be far less complex and intrusive than the mods 
that you suggest below.

I have not implemented this scheme under Linux,
but we have tried it with success under other OSes.
It should in principle be SMP safe.

> Technical discussions are welcome.

Well, there you have one!

            Regards,

            Kevin K.

^ permalink raw reply

* Re: metadata and contents in loop device
From: Lars Marowsky-Bree @ 2002-01-22 18:18 UTC (permalink / raw)
  To: Michael Zhu; +Cc: linux-crypto, linux-kernel
In-Reply-To: <20020122180201.42898.qmail@web14905.mail.yahoo.com>

On 2002-01-22T13:02:01,
   Michael Zhu <mylinuxk@yahoo.ca> said:

> Hello, everyone, in my loop device I want to use
> different keys to en/decrypt the file contents and the
> metadata of directories/file names information. But
> how can I differentiate these two types of data in the
> loop device? The loop device just cares about the
> block. But the metadata of directories/file names
> information is just the file system information. Any
> idea about this? Thanks in advance.

You can't.

Not without a special filesystem, which stored both kinds of data on different
block devices. Have fun writing one ;-)

What is the intended use of this?


Sincerely,
    Lars Marowsky-Brée <lmb@suse.de>

-- 
Perfection is our goal, excellence will be tolerated. -- J. Yahl


^ permalink raw reply

* Re: thread-ready ABIs
From: Kevin D. Kissell @ 2002-01-22 18:18 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Dominic Sweetman, Ralf Baechle, Ulrich Drepper, Mike Uhler,
	MIPS/Linux List (SGI), H . J . Lu
In-Reply-To: <20020122125747.A18040@nevyn.them.org>

> No, you didn't read my manpage quote, Kevin.  Or we're just talking
> past each other.  The problem is not that existing mappings are shared,
> but that "any memory mapping or unmapping performed with mmap(2)
> or munmap(2) by the child or calling process also affects the other
> process".  That is, if the child maps some private storage, the parent
> will see it too.  Thus we can not use the private storage as a
> thread-local storage unless we already have some thread-local way to
> say where it is for this particular thread, and we're back where we
> started.
> 
> Does that make sense, or am I missing your objection?

It doen't necessarily make *sense*, in that it seems to
be a pretty crippled memory model ;-) but I do see your
objection.  Sorry to have seemed dense, I'm doing several
things at once on a couple of screens this evening and
reading too quickly.  I had misread that as underscoring
that the effects of mmaps() *prior* to the clone() were
inherited.  Feh.  Well, we aren't likely to have the luxury
of fixing the underlying design of pthreads for Linux
to use a fork()-based model with explicit sharing
(which has its own problems, of course), so we may well 
be looking at ABI abuse.  I was really, really, hoping 
to avoid that, in that gcc/Linux is far from the only user 
(and commercially speaking, far from being the most 
important user) of the ABI, and any change that breaks 
backward compatibility and cross-platform compatibility 
would be a Very Bad Thing.

More on this later, and thanks for your (civil) comments,

            Kevin K.

^ permalink raw reply

* Re: Why not "attach" patches?
From: H. Peter Anvin @ 2002-01-22 18:17 UTC (permalink / raw)
  To: linux-kernel
In-Reply-To: <E16Sh69-0001iV-00@starship.berlin>

Followup to:  <E16Sh69-0001iV-00@starship.berlin>
By author:    Daniel Phillips <phillips@bonn-fries.net>
In newsgroup: linux.dev.kernel
> 
> Kmail's patch-mangling problems seem to be all gone in kmail 2.2+.  The only 
> thing to be careful about is that word wrap should be off.  Since I
> forgot to
> turn it off a couple of times I now leave it permanently off and turn it on 
> for individual mails as needed.
> 

The common ground most people seems to be able to accept is:

a. Go ahead and make patches as attachments, if your MUA makes it easier;
b. Be bloody certain they're text/plain attachments.

	-hpa
-- 
<hpa@transmeta.com> at work, <hpa@zytor.com> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt	<amsp@zytor.com>

^ permalink raw reply

* Re: patches for test-and-set without ll/sc (Re: thread-ready ABIs)
From: Kevin D. Kissell @ 2002-01-22 18:19 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: linux-mips
In-Reply-To: <Pine.LNX.3.96.1020122110419.20690A-100000@wakko.deltatee.com>

> On Tue, 22 Jan 2002, Kevin D. Kissell wrote:
> 
> > The idea leverages off the fact that a branch likely
> > instruction performs a kind of conditional execution.
> > The instruction in the delay slot is executed only if
> > the branch is taken.  This can be used to synthesize
> > a conditional store.  The user level code for a simple
> > atomic increment, for example, would look something
> > like this:
> 
> Hmm, could you use this to take the race out of the kernel wait loop 
> too? Ie use current->need_resched as the test and 'wait' as the
> conditional operation.

It's quite possible.  But remember that it won't work on
an R3000.  R39xx yes, but not an R3K "classic".

            Kevin K.

^ permalink raw reply

* SCSI AIC7xxx driver hang on alpha
From: Fabrice Peix @ 2002-01-22 18:27 UTC (permalink / raw)
  To: linux-kernel



	Yop,

	During init of SCSI (boot time) the system hang

	I use kernel 2.4.17 on alpha lx164 motherboard.

	bye.
 

^ permalink raw reply

* Linux 2.4.18-pre5
From: Marcelo Tosatti @ 2002-01-22 17:20 UTC (permalink / raw)
  To: lkml


Hi, 

I was waiting for the icmp overflow problem to be fixed to release this
kernel, but it only exists only on 2.2.

Well, here goes pre5.


pre5:

- Include missing radeonfb defines		(Erik Andersen)
- Fix fs/buffer.c thinko introduced in pre4	(Andrew Morton)
- USB bugfixes					(Greg KH)
- Make fat work correctly with gcc-3.0.x 	(Tom Rini)
- Avoid overusage of the vmalloc area by 
  NTFS						(Anton Altaparmakov)
- atyfb: Decrease clock rate for 3d RAGE XL 	(David S. Miller)
- Sungem driver bugfixes			(David S. Miller)
- More networking updates			(David S. Miller)
- More SPARC updates				(David S. Miller)
- devfs update 					(Richard Gooch)
- Reiserfs expanding truncate fix		(Chris Mason)
- ext3 update					(Andrew Morton/Stephen Tweedie)
- Add support to WDIOC_SETTIMEOUT on several
  watchdog drivers				(Joel Becker)
- dl2k driver update				(Jeff Garzik)
- Orinoco driver update				(David Gibson)
- Radeonfb driver update			(Ani Joshi)
- Avoid free_swap_and_cache() from leaving 
  freeable pages on the cache			(Hugh Dickins)
- Add workarounds for AMD Elan processors	(Robert Schwebel)
- Random pmac driver bugfixing			(Benjamin Herrenschmidt)
- emu10k1 driver update				(Rui Sousa)

pre4:

- Networking updates				(David S. Miller)
- clgenfb update				(Jeff Garzik)
- 8139cp: make it faster			(Jeff Garzik)
- 8139too: fix bugs, add experimental RX reset	(Jeff Garzik)
- Add MII ethtool interface and change 
  several drivers to support that		(Jeff Garzik)
- Fix ramdisk corruption problems		(Andrea Arcangeli) 	
- Correct in-kernel MS_ASYNC behaviour 
  on msync/fsync()				(Andrew Morton)
- Fix PLIP problems 				(Niels Jensen)
- Fix problems triggered by the "fsx test" 
  on smbfs					(Urban Widmark)
- Turn on OOSTORE for IDT winchip		(from -ac tree)
- Fix iphase crash				(from -ac tree)
- Fix crash with two mxser cards		(from -ac tree)
- Fix tty write block bug			(from -ac tree)
- Add mono/stereo detect to gemtek pci radio	(from -ac tree)
- Fix sf16fmi crash on load			(from -ac tree)
- add CP1250 (windows eastern european) 
  translation table				(from -ac tree)
- cs46xx driver update				(from -ac tree)
- Fix rare data loss case with RAID-1		(Ingo Molnar)
- Add 2.5.x compatibility for the kdev_t
  changes					(me)
- SPARC updates					(David S. Miller)

pre3:

- Cris arch merge				(Bjorn Wesen)
- Finish PPC merge				(Benjamin Herrenschmidt)
- Add Dell PowerEdge 2400 to 
  "use BIOS to reboot" blacklist		(Arjan van de Ven)
- Avoid potential oops at module unload with 
  cyclades driver				(Andrew Morton)
- Gracefully handle SCSI initialization 
  failures					(Pete Zaitcev)
- USB update					(Greg KH)
- Fix potential oops while ejecting ide cds 	(Zwane Mwaikambo)
- Unify page freeing codepaths 			(Benjamin LaHaise)
- Miata dma corruption workaround 		(Richard Henderson)
- Fix vmalloc corruption problem on machines 
  with virtual dcaches				(Ralf Baechle)
- Reiserfs fixes				(Oleg Drokin)
- DiskOnChip driver update			(David Woodhouse)
- Do not inherit page locking rules across 
  fork/exec					(Dave Anderson)
- Add DRM 4.0 for XFree 4.0 users convenience	(Christoph Hellwig)
- Replace .text.lock with .subsection 		(Keith Owens)
- IrDA bugfixes					(Jean Tourrilhes)

pre2: 

- APIC LVTERR fixes				(Mikael Pettersson)
- Fix ppdev ioctl oops and deadlock		(Tim Waugh)
- parport fixes					(Tim Waugh)
- orinoco wireless driver update		(David Gibson)
- Fix oopsable race in binfmt_elf.c 		(Alexander Viro)
- Small sx16 driver bugfix			(Heinz-Ado Arnolds)
- sbp2 deadlock fix 				(Andrew Morton)
- Fix JFFS2 write error handling		(David Woodhouse)
- Intermezzo update				(Peter J. Braam)
- Proper AGP support for Intel 830MP chipsets	(Nicolas Aspert)
- Alpha fixes					(Jay Estabrook)
- 53c700 SCSI driver update			(James Bottomley)
- Fix coredump mmap_sem deadlock on IA64	(David Mosberger)
- 3ware driver update				(Adam Radford)
- Fix elevator insertion point on failed 
  request merge					(Jens Axboe)
- Remove bogus rpciod_tcp_dispatcher definition (David Woodhouse)
- Reiserfs fixes				(Oleg Drokin)
- de4x5 endianess fixes				(Kip Walker)
- ISDN CAPI cleanup				(Kai Germaschewski)
- Make refill_inactive() correctly account 
  progress					(me)

pre1:

- S390 merge					(IBM)
- SuperH merge					(SuperH team)
- PPC merge					(Benjamin Herrenschmidt)
- PCI DMA update				(David S. Miller)
- radeonfb update 				(Ani Joshi)
- aty128fb update				(Ani Joshi)
- Add nVidia GeForce3 support to rivafb		(Ani Joshi)
- Add PM support to opl3sa2			(Zwane Mwaikambo)
- Basic ethtool support for 3com, starfire
  and pcmcia net drivers			(Jeff Garzik)
- Add MII ethtool interface			(Jeff Garzik)
- starfire,sundance,dl2k,sis900,8139{too,cp},
  natsemi driver updates			(Jeff Garzik)
- ufs/minix: mark inodes as bad in case of read
  failure					(Christoph Hellwig)
- ReiserFS fixes				(Oleg Drokin)
- sonypi update					(Stelian Pop)
- n_hdlc update					(Paul Fulghum)
- Fix compile error on aty_base.c		(Tobias Ringstrom)
- Document cpu_to_xxxx() on kernel-hacking doc  (Rusty Russell)
- USB update					(Greg KH)
- Fix sysctl console loglevel bug on 
  IA64 (and possibly other archs)		(Jesper Juhl) 
- Update Athlon/VIA PCI quirks			(Calin A. Culianu)
- blkmtd update					(Simon Evans)
- boot protocol update (makes the highest 
  possible initrd address available to the 
  bootloader)					(H. Peter Anvin)
- NFS fixes					(Trond Myklebust)


^ permalink raw reply

* Re: usb-problems with Au1000
From: Pete Popov @ 2002-01-22 17:33 UTC (permalink / raw)
  To: Kunihiko IMAI; +Cc: linux-mips
In-Reply-To: <m37kqa7lpq.wl@l5ac152.l5.laser5.co.jp>

On Tue, 2002-01-22 at 01:56, Kunihiko IMAI wrote:
> Hi,
> 
> At 18 Jan 2002 11:49:09 -0800,
> Pete Popov wrote:
> > 
> > 
> > > > It's the comment that's wrong, not the code. The code works and has been
> > > > tested.  Alchemy makes available the Linux Support Package (LSP) which
> > > > we did. That kernel has been tested with all peripherals so I would
> > > > recommend that you get that from them.  Also,make sure your jumpers are
> > > > setup correctly (S4).
> > > 
> > > In the source code:
> > > 
> > > 	sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
> > > 
> > > 	(snip...)
> > > 
> > > 	outl(sys_clksrc, CLOCK_SOURCE_CNTRL);
> > > 
> > > This code sets the clock source of USB host controller is FREQ2.  So
> > > FREQ5 clock source doesn't affect to USB host controller.
> > 
> > After looking into it, both the comment and code are correct. From
> > include/asm-mips/au1000.h:
> > 
> > #define FQ_CNTRL_1                0xB1900020
> > #define FQ_CNTRL_2                0xB1900024
> > 
> > So FQ_CNTRL_1 corresponds to what is now sys_freqctrl0. In other words,
> > the update to the databook has not been incorporated into the Au1000
> > files. The names of the registers were updated after I had done all the
> > core work. I need to update the code so the names of the registers
> > correspond to the latest Au1000 manual.
> 
> Oh, I see.  I'm sorry for my misunderstanding.

It's OK, one of these days I'll have time to rename all the registers to
match the last data book.

Pete
 
> Now the relations are like this:
> 
> Au1000 manual	Linux Header
> -----------------------------------
> sys_freqctl0	FQ_CNTRL_1
> sys_freqctl1	FQ_CNTRL_2
> -----------------------------------

^ permalink raw reply

* Re: [parisc-linux] vmlinux header for savecrash.
From: Grant Grundler @ 2002-01-22 18:34 UTC (permalink / raw)
  To: Bruno Vidal; +Cc: parisc-linux@lists.parisc-linux.org
In-Reply-To: <3C4DA793.B17F1D3C@admin.france.hp.com>

Bruno Vidal wrote:
> 	Hi
> I don't know how to retrieve option pass to the kernel,
> but give me some clue, and I'll add this information in
> the dump header asap, because it is a really good idea :-)

(credit: Randolph brought it up first)

Look at arch/parisc/kernel/setup.c:setup_cmdline().
We can add pretty much anything we need here.

It just occurred to me that the source media (ie network, disk)
needs to be identified as well.
Is the vmlinux/System.map required to be on the root file system?
Would it be reasonble if savecrash told the user that /boot/vmlinux
wasn't the matching kernel and where to put the right vmlinux/System.map?

Allowing users to drop the right kernel in place *after* the
crash dump was recovered seems reasonable thing to do.
Someone might want to move the crash dump to a bigger/faster
system to do the actual analysis.

grant

^ permalink raw reply

* Re: thread-ready ABIs
From: Kevin D. Kissell @ 2002-01-22 17:34 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Dominic Sweetman, Ralf Baechle, Ulrich Drepper, Mike Uhler,
	MIPS/Linux List (SGI), H . J . Lu
In-Reply-To: <20020122121330.A16110@nevyn.them.org>

> > > Perhaps I'm mangling terminology.  LinuxThreads is a one-to-one
mapping
> > > of kernel threads to user threads.  All the kernel threads, and thus
> > > all the user threads, share the same memory region - including the
> > > stack region.  Their stacks are differentiated solely by different
> > > values in the stack pointer register.  Thus I don't think what you're
> > > suggesting is possible.
> >
> > I don't see how fork() semantics can be preserved unless
> > the stack regions are replicated (copy-on-write) on a fork().
> > Under ATT and BSD Unix (which is where I did most of
> > my kernel hacking in the old days) that was the *only*
> > way to get a new kernel thread, so it was "obvious"
> > that my proposed hack would work.  Linux does have
> > the clone() function as well, and if LinuxThreads are
> > implemented in terms of clone(foo, stakptr, CLONE_VM, arg),
> > you are correct, the proposed scheme would not work
> > without modification.
>
> Which it is.  Fork shares no memory regions;

Oh, come on.  If it doesn't share text regions, it's completely
brain dead!

> vfork/clone share all memory regions.  AFAIK there is no
> share-heap-but-not-stack option in Linux.

Yeah.  Not that it matters, but I had misremebered there being
finer grained control than that on clone().  Probably confused
it with something that someone overlaid on Mach once upon a time...

Anyway, do you see a hole or a serious performance
problem with my modified proposal (explicit mmap()
to create the necessary storage)?


            Regards,

            Kevin K.

^ permalink raw reply

* Re: metadata and contents in loop device
From: Xavier Bestel @ 2002-01-22 18:28 UTC (permalink / raw)
  To: Michael Zhu; +Cc: linux-crypto, Linux Kernel Mailing List
In-Reply-To: <20020122180201.42898.qmail@web14905.mail.yahoo.com>

On Tue, 2002-01-22 at 19:02, Michael Zhu wrote:
> Hello, everyone, in my loop device I want to use
> different keys to en/decrypt the file contents and the
> metadata of directories/file names information. But
> how can I differentiate these two types of data in the
> loop device? The loop device just cares about the
> block. But the metadata of directories/file names
> information is just the file system information. Any
> idea about this? Thanks in advance.

Mmmh ... I don't really see the point, but perhaps you should look at
stegfs (sorry, don't remember the URL)



^ permalink raw reply

* [PATCH] 2.5.2 pthread support for SEM_UNDO in semop()
From: Dave Olien @ 2002-01-22 18:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: torvalds


[PATCH] 2.5.2 pthread support for SEM_UNDO in semop()

I apologize, I neglected to include the patch in my last submission.

The Linux semop() System V semaphore SEM_UNDO should perform SEM_UNDO cleanup
during "process" exit, not during "pthread" exit.  Following is a brief
explanation of the problem, followed by the test program,
followed by a patch for linux 2.4.17.

The test program is pretty simple.  The application creates
several threads using pthread_create().  When one thread performs a semop()
with the SEM_UNDO flag set, the change in sempaphore value performed by
that semop should be "undone" only when the entire application exits, NOT when
that thread exits.  This would be consistent with the description on the
semop(2) manual page, and also with the semop() implementation on many other
UNIX implementations.

However, In the current Linux implementation, the semop is "undone" when the
thread that performed the semop() exits.  This is too soon.  This behavior
has created difficulty in porting to Linux some threaded applications that use
semop().

In the current Linux implementation, each thread currently maintains its own
private list of semundo structures, referenced by current->semundo.  The bug
is that the list of sem_undo structures for a threaded process should be
shared among all the threads in that process.

My patch adds a structure (sem_undohd) that is shared by all the threads in
the threaded application, and controls access to the shared list of sem_undo
structures. current->semundo references are replaced with current->semundohd
references.  I've tried to minimize the impact on tasks that are not using
SEM_UNDO semop() operations, or that are not using pthread_create().

One issue is WHEN should a child task share its sem_undo structures list with
its parent.  Linux uses a collection of flags (CLONE_VM, CLONE_FS, etc) to the
fork() system call, to cause the child task to share various components of
the parent's state.  There is no flag indicating when the child task should
share sem_undo state.  When should a parent task and its child conform to the
POSIX threads behavior for system V semaphores? See the code in copy_semundo()
for how this decision was made.

Below is a test program for this.  The test program's output SHOULD look like:

Waiter, pid = 11490
Poster, pid = 11490, posting
Poster posted
Poster exiting
Waiter waiting, pid = 11490
Waiter done waiting

The Incorrect output on Linux is:

Waiter, pid = 712
Poster, pid = 713, posting
Poster posted
Poster exiting
Waiter waiting, pid = 712


---------------------tsem.c---------------------------------------------------

#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
#include <errno.h>
#include <pthread.h>

#define KEY 0x1234

#define NUMTHREADS 2

void *retval[NUMTHREADS]; 
void * waiter(void *);
void * poster(void *);

struct sembuf Psembuf = {0, -1, SEM_UNDO};
struct sembuf Vsembuf = {0, 1, SEM_UNDO};

int sem_id;

main()
{
    int i, pid, rc;
    
    pthread_t pt[NUMTHREADS];
    pthread_attr_t attr;

    /* Create the semaphore set */
    sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
    if (sem_id < 0)
    {
	printf ("semget failed, errno = %d\n", errno);
	exit (1);
    }
    
    /* setup the attributes of the thread        */
    /* set the scope to be system to make sure the process competes on a  */
    /* global scale for cpu   */
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    /* Create the threads */
    for (i=0; i<NUMTHREADS; i++)
    {
	if (i == 0)
	    rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
	else
	    rc = pthread_create(&pt[i], &attr, poster, retval[i]);
    }

    /* Sleep long enough to see that the other threads do what they are supposed to do */
    sleep(20);

    exit(0);
}


/* This thread sleeps 10 seconds then waits on the semaphore.  As long
   as someone has posted on the semaphore, and no undo has taken
   place, the semop should complete and we'll print "Waiter done
   waiting." */
void * waiter(void * foo)
{
    int pid;
    pid = getpid();

    printf ("Waiter, pid = %d\n", pid);
    sleep(10);

    printf("Waiter waiting, pid = %d\n", pid);
    semop(sem_id, &Psembuf, 1);
    printf("Waiter done waiting\n");
   
    pthread_exit(0);
}

/* This thread immediately posts on the semaphore and then immediately
   exits.  If the *thread* exits, the undo should not happen, and the
   waiter thread which will start waiting on it in 10 seconds, should
   still get it.   */
void * poster(void * foo)
{
    int pid;
   
    pid = getpid();
    printf ("Poster, pid = %d, posting\n", pid);
    semop(sem_id, &Vsembuf, 1);
    printf ("Poster posted\n");
    printf ("Poster exiting\n");
    
    pthread_exit(0);
}

------------------------Begin Patch for linux 2.5.2-------------------------

diff -urN --exclude-from=/usr/src/dontdiff linux-2.5.2_original/linux/include/linux/sched.h linux-2.5.2_SEMUNDO/linux/include/linux/sched.h
--- linux-2.5.2_original/linux/include/linux/sched.h	Mon Jan 14 13:27:08 2002
+++ linux-2.5.2_SEMUNDO/linux/include/linux/sched.h	Mon Jan 21 19:23:53 2002
@@ -372,7 +372,7 @@
 	struct tty_struct *tty; /* NULL if no tty */
 	unsigned int locks; /* How many file locks are being held */
 /* ipc stuff */
-	struct sem_undo *semundo;
+	struct sem_undohd *semundohd;
 	struct sem_queue *semsleeping;
 /* CPU-specific state of this task */
 	struct thread_struct thread;
diff -urN --exclude-from=/usr/src/dontdiff linux-2.5.2_original/linux/include/linux/sem.h linux-2.5.2_SEMUNDO/linux/include/linux/sem.h
--- linux-2.5.2_original/linux/include/linux/sem.h	Mon Jan 14 13:27:06 2002
+++ linux-2.5.2_SEMUNDO/linux/include/linux/sem.h	Mon Jan 21 19:23:53 2002
@@ -121,6 +121,18 @@
 	short *			semadj;		/* array of adjustments, one per semaphore */
 };
 
+/* Each PROCESS (i.e. collection of tasks that are running POSIX style threads)
+ * must share the same semundo list, in order to support POSIX SEMUNDO
+ * semantics for threads.  The sem_undohd controls shared access to this
+ * list among all the tasks (threads) in that process.
+ */ 
+struct sem_undohd {
+	atomic_t	refcnt;
+	spinlock_t	lock;
+	volatile unsigned long	add_count;
+	struct sem_undo	*proc_list;
+};
+
 asmlinkage long sys_semget (key_t key, int nsems, int semflg);
 asmlinkage long sys_semop (int semid, struct sembuf *sops, unsigned nsops);
 asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg);
diff -urN --exclude-from=/usr/src/dontdiff linux-2.5.2_original/linux/ipc/sem.c linux-2.5.2_SEMUNDO/linux/ipc/sem.c
--- linux-2.5.2_original/linux/ipc/sem.c	Sun Sep 30 12:26:42 2001
+++ linux-2.5.2_SEMUNDO/linux/ipc/sem.c	Mon Jan 21 19:08:40 2002
@@ -788,12 +788,75 @@
 	}
 }
 
-static struct sem_undo* freeundos(struct sem_array *sma, struct sem_undo* un)
+static inline void lock_semundo(void)
+{
+	struct sem_undohd *undohd;
+
+	undohd = current->semundohd;
+	if ((undohd != NULL) && (atomic_read(&undohd->refcnt) != 1))
+		spin_lock(&undohd->lock);
+}
+
+/* This code has an interesting interaction with copy_semundo():
+ * two tasks could have been sharing the semundohd at the time "first" one
+ * of those tasks acquires the lock acquired in lock_semundo.  If the other
+ * tasks exits before * "the first one" releases the lock (by calling
+ * unlock_semundo), then the spin_unlock would NOT be called.  This would
+ * leave the semundohd in a locked state.  This would NOT be a problem unless
+ * the remaining task once again creates a new task that once again shares the
+ * semundohd.  Cleanup up this last case is dealt with in copy_semundo by
+ * having it reinitialize the spin_lock when it once again creates a second
+ * task sharing the semundo.
+ */
+static inline void unlock_semundo(void)
+{
+	struct sem_undohd *undohd;
+
+	undohd = current->semundohd;
+	if ((undohd != NULL) && (atomic_read(&undohd->refcnt) != 1))
+		spin_unlock(&undohd->lock);
+}
+
+
+/* If the task doesn't already have a semundohd, then allocate one
+ * here.  We guarantee there is only one thread using this undo list,
+ * and current is THE ONE
+ *
+ * If this allocation and assignment succeeds, but later
+ * portions of this code fail, there is no need to free the sem_undohd.
+ * Just let it stay associated with the task, and it'll be freed later
+ * at exit time.
+ *
+ * This can block, so callers must hold no locks.
+ */
+static inline int get_undohd(struct sem_undohd **undohdp)
+{
+	struct sem_undohd *undohd;
+	int size;
+
+	undohd = current->semundohd;
+	if (!undohd) {
+		size = sizeof(struct sem_undohd);
+		undohd = (struct sem_undohd *) kmalloc(size, GFP_KERNEL);
+		if (undohd == NULL)
+			return -ENOMEM;
+		memset(undohd, 0, size);
+		/* don't initialize unodhd->lock here.  It's done
+		 * in copy_semundo() instead.
+		 */
+		atomic_set(&undohd->refcnt, 1);
+		current->semundohd = undohd;
+	}
+	*undohdp = undohd;
+	return 0;
+}
+
+static struct sem_undo* freeundos(struct sem_undo* un)
 {
 	struct sem_undo* u;
 	struct sem_undo** up;
 
-	for(up = &current->semundo;(u=*up);up=&u->proc_next) {
+	for(up = &current->semundohd->proc_list;(u=*up);up=&u->proc_next) {
 		if(un==u) {
 			un=u->proc_next;
 			*up=un;
@@ -805,33 +868,87 @@
 	return un->proc_next;
 }
 
-/* returns without sem_lock on error! */
+static inline struct sem_undo *find_undo(int semid)
+{
+	struct sem_undo *un;
+
+	un = NULL;
+	if (current->semundohd != NULL) {
+		un = current->semundohd->proc_list;
+	}
+	while(un != NULL) {
+		if(un->semid==semid)
+			break;
+		if(un->semid==-1)
+			un=freeundos(un);
+		 else
+			un=un->proc_next;
+	}
+	return un;
+}
+
+/* returns without sem_lock and semundo list locks on error! */
 static int alloc_undo(struct sem_array *sma, struct sem_undo** unp, int semid, int alter)
 {
 	int size, nsems, error;
-	struct sem_undo *un;
+	struct sem_undo *un, *new_un;
+	struct sem_undohd *unhd;
+	unsigned long	saved_add_count;
+
 
 	nsems = sma->sem_nsems;
-	size = sizeof(struct sem_undo) + sizeof(short)*nsems;
+	saved_add_count = 0;
+	if (current->semundohd != NULL)
+		saved_add_count = current->semundohd->add_count;
 	sem_unlock(semid);
+	unlock_semundo();
 
+	error = get_undohd(&unhd);
+	if (error)
+		return error;
+
+	size = sizeof(struct sem_undo) + sizeof(short)*nsems;
 	un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
 	if (!un)
 		return -ENOMEM;
 
 	memset(un, 0, size);
+	lock_semundo();
 	error = sem_revalidate(semid, sma, nsems, alter ? S_IWUGO : S_IRUGO);
 	if(error) {
+		unlock_semundo();
 		kfree(un);
 		return error;
 	}
 
-	un->semadj = (short *) &un[1];
-	un->semid = semid;
-	un->proc_next = current->semundo;
-	current->semundo = un;
-	un->id_next = sma->undo;
-	sma->undo = un;
+
+	/* alloc_undo has just
+	 * released all locks and reacquired them. 
+	 * But, another thread may have
+	 * added the semundo we were looking for
+	 * during that time.
+	 * So, we check for it again.
+	 * only initialize and add the new one
+	 * if we don't discover one.
+	 */
+	new_un = NULL;
+	if (current->semundohd->add_count != saved_add_count)
+		new_un = find_undo(semid);
+
+	if (new_un != NULL) {
+		if (sma->undo != new_un)
+			BUG();
+		kfree(un);
+		un = new_un;
+	} else {
+		current->semundohd->add_count++;
+		un->semadj = (short *) &un[1];
+		un->semid = semid;
+		un->proc_next = unhd->proc_list;
+		unhd->proc_list = un;
+		un->id_next = sma->undo;
+		sma->undo = un;
+	}
 	*unp = un;
 	return 0;
 }
@@ -846,6 +963,7 @@
 	int undos = 0, decrease = 0, alter = 0;
 	struct sem_queue queue;
 
+
 	if (nsops < 1 || semid < 0)
 		return -EINVAL;
 	if (nsops > sc_semopm)
@@ -859,17 +977,18 @@
 		error=-EFAULT;
 		goto out_free;
 	}
+	lock_semundo();
 	sma = sem_lock(semid);
 	error=-EINVAL;
 	if(sma==NULL)
-		goto out_free;
+		goto out_semundo_free;
 	error = -EIDRM;
 	if (sem_checkid(sma,semid))
-		goto out_unlock_free;
+		goto out_unlock_semundo_free;
 	error = -EFBIG;
 	for (sop = sops; sop < sops + nsops; sop++) {
 		if (sop->sem_num >= sma->sem_nsems)
-			goto out_unlock_free;
+			goto out_unlock_semundo_free;
 		if (sop->sem_flg & SEM_UNDO)
 			undos++;
 		if (sop->sem_op < 0)
@@ -881,24 +1000,18 @@
 
 	error = -EACCES;
 	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-		goto out_unlock_free;
+		goto out_unlock_semundo_free;
 	if (undos) {
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
 		 */
-		un=current->semundo;
-		while(un != NULL) {
-			if(un->semid==semid)
-				break;
-			if(un->semid==-1)
-				un=freeundos(sma,un);
-			 else
-				un=un->proc_next;
-		}
+		
+		un = find_undo(semid);
 		if (!un) {
 			error = alloc_undo(sma,&un,semid,alter);
-			if(error)
+			if (error)
 				goto out_free;
+
 		}
 	} else
 		un = NULL;
@@ -930,16 +1043,18 @@
 		queue.sleeper = current;
 		current->state = TASK_INTERRUPTIBLE;
 		sem_unlock(semid);
+		unlock_semundo();
 
 		schedule();
 
+		lock_semundo();
 		tmp = sem_lock(semid);
 		if(tmp==NULL) {
 			if(queue.prev != NULL)
 				BUG();
 			current->semsleeping = NULL;
 			error = -EIDRM;
-			goto out_free;
+			goto out_semundo_free;
 		}
 		/*
 		 * If queue.status == 1 we where woken up and
@@ -960,7 +1075,7 @@
 				break;
 			/* Everything done by update_queue */
 			current->semsleeping = NULL;
-			goto out_unlock_free;
+			goto out_unlock_semundo_free;
 		}
 	}
 	current->semsleeping = NULL;
@@ -968,14 +1083,61 @@
 update:
 	if (alter)
 		update_queue (sma);
-out_unlock_free:
+out_unlock_semundo_free:
 	sem_unlock(semid);
+out_semundo_free:
+	unlock_semundo();
 out_free:
 	if(sops != fast_sops)
 		kfree(sops);
 	return error;
 }
 
+/* For now, assume that if ALL clone flags are set, then
+ * we must be creating a POSIX thread, and we want undo lists
+ * to be shared among all the threads in that thread group.
+ *
+ * See the notes above unlock_semundo() regarding the spin_lock_init()
+ * in this code.  Initialize the undohd->lock here instead of get_undohd()
+ * because of the reasoning in the note referenced here.
+ */
+#define CLONE_SEMUNDO (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND)
+
+int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
+{
+	struct sem_undohd *undohd;
+	int error;
+
+	if (((clone_flags & CLONE_SEMUNDO) == CLONE_SEMUNDO) ||
+		(clone_flags & CLONE_THREAD)) {
+		error = get_undohd(&undohd);
+		if (error)
+			return error;
+		if (atomic_read(&undohd->refcnt) == 1)
+			spin_lock_init(&undohd->lock);
+		atomic_inc(&undohd->refcnt);
+		tsk->semundohd = undohd;
+	} else 
+		tsk->semundohd = NULL;
+
+	return 0;
+}
+
+static inline void __exit_semundo(struct task_struct *tsk)
+{
+	struct sem_undohd *unhd;
+
+	unhd = tsk->semundohd;
+	if (!atomic_dec_and_test(&unhd->refcnt))
+		kfree(unhd);
+}
+
+void exit_semundo(struct task_struct *tsk)
+{
+	if (tsk->semundohd != NULL)
+		__exit_semundo(tsk);
+}
+
 /*
  * add semadj values to semaphores, free undo structures.
  * undo structures are not freed when semaphore arrays are destroyed
@@ -993,6 +1155,7 @@
 	struct sem_queue *q;
 	struct sem_undo *u, *un = NULL, **up, **unp;
 	struct sem_array *sma;
+	struct sem_undohd *undohd;
 	int nsems, i;
 
 	/* If the current process was sleeping for a semaphore,
@@ -1012,7 +1175,14 @@
 			sem_unlock(semid);
 	}
 
-	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
+	undohd = current->semundohd;
+	if ((undohd == NULL) || (atomic_read(&undohd->refcnt) != 1))
+		return;
+
+	/* There's no need to hold the semundo list lock, as current
+         * is the last task exiting for this undo list.
+	 */
+	for (up = &undohd->proc_list; (u = *up); *up = u->proc_next, kfree(u)) {
 		int semid = u->semid;
 		if(semid == -1)
 			continue;
@@ -1050,7 +1220,7 @@
 next_entry:
 		sem_unlock(semid);
 	}
-	current->semundo = NULL;
+	__exit_semundo(current);
 }
 
 #ifdef CONFIG_PROC_FS
diff -urN --exclude-from=/usr/src/dontdiff linux-2.5.2_original/linux/ipc/util.c linux-2.5.2_SEMUNDO/linux/ipc/util.c
--- linux-2.5.2_original/linux/ipc/util.c	Sun Aug 12 17:37:53 2001
+++ linux-2.5.2_SEMUNDO/linux/ipc/util.c	Mon Jan 21 19:08:40 2002
@@ -340,6 +340,17 @@
  * Dummy functions when SYSV IPC isn't configured
  */
 
+int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
+{
+	return 0;
+}
+
+void exit_semundo(struct task_struct *tsk)
+{
+	return;
+}
+
+
 void sem_exit (void)
 {
     return;
diff -urN --exclude-from=/usr/src/dontdiff linux-2.5.2_original/linux/kernel/fork.c linux-2.5.2_SEMUNDO/linux/kernel/fork.c
--- linux-2.5.2_original/linux/kernel/fork.c	Wed Jan  9 16:16:28 2002
+++ linux-2.5.2_SEMUNDO/linux/kernel/fork.c	Mon Jan 21 19:19:10 2002
@@ -27,6 +27,9 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
+extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk);
+extern void exit_semundo(struct task_struct *tsk);
+
 /* The idle threads do not count.. */
 int nr_threads;
 
@@ -662,8 +665,10 @@
 
 	retval = -ENOMEM;
 	/* copy all the process information */
-	if (copy_files(clone_flags, p))
+	if (copy_semundo(clone_flags, p))
 		goto bad_fork_cleanup;
+	if (copy_files(clone_flags, p))
+		goto bad_fork_cleanup_semundo;
 	if (copy_fs(clone_flags, p))
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
@@ -675,7 +680,6 @@
 	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
 		goto bad_fork_cleanup_namespace;
-	p->semundo = NULL;
 	
 	/* Our parent execution domain becomes current domain
 	   These must match for thread signalling to apply */
@@ -773,6 +777,8 @@
 	exit_fs(p); /* blocking */
 bad_fork_cleanup_files:
 	exit_files(p); /* blocking */
+bad_fork_cleanup_semundo:
+	exit_semundo(p);
 bad_fork_cleanup:
 	put_exec_domain(p->exec_domain);
 	if (p->binfmt && p->binfmt->module)

^ permalink raw reply

* [PATCH] 2.4.17 pthread support for SEM_UNDO in semop()
From: Dave Olien @ 2002-01-22 18:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: marcelo


[PATCH] 2.4.17 pthread support for SEM_UNDO in semop()

My apologies.  I neglected to include the patch in my last submission.

The Linux semop() System V semaphore SEM_UNDO should perform SEM_UNDO cleanup
during "process" exit, not during "pthread" exit.  Following is a brief
explanation of the problem, followed by the test program,
followed by a patch for linux 2.4.17.

The test program is pretty simple.  The application creates
several threads using pthread_create().  When one thread performs a semop()
with the SEM_UNDO flag set, the change in sempaphore value performed by
that semop should be "undone" only when the entire application exits, NOT when
that thread exits.  This would be consistent with the description on the
semop(2) manual page, and also with the semop() implementation on many other
UNIX implementations.

However, In the current Linux implementation, the semop is "undone" when the
thread that performed the semop() exits.  This is too soon.  This behavior
has created difficulty in porting to Linux some threaded applications that use
semop().

In the current Linux implementation, each thread currently maintains its own
private list of semundo structures, referenced by current->semundo.  The bug
is that the list of sem_undo structures for a threaded process should be
shared among all the threads in that process.

My patch adds a structure (sem_undohd) that is shared by all the threads in
the threaded application, and controls access to the shared list of sem_undo
structures. current->semundo references are replaced with current->semundohd
references.  I've tried to minimize the impact on tasks that are not using
SEM_UNDO semop() operations, or that are not using pthread_create().

One issue is WHEN should a child task share its sem_undo structures list with
its parent.  Linux uses a collection of flags (CLONE_VM, CLONE_FS, etc) to the
fork() system call, to cause the child task to share various components of
the parent's state.  There is no flag indicating when the child task should
share sem_undo state.  When should a parent task and its child conform to the
POSIX threads behavior for system V semaphores? See the code in copy_semundo()
for how this decision was made.

Below is a test program for this.  The test program's output SHOULD look like:

Waiter, pid = 11490
Poster, pid = 11490, posting
Poster posted
Poster exiting
Waiter waiting, pid = 11490
Waiter done waiting

The Incorrect output on Linux is:

Waiter, pid = 712
Poster, pid = 713, posting
Poster posted
Poster exiting
Waiter waiting, pid = 712


---------------------tsem.c---------------------------------------------------

#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
#include <errno.h>
#include <pthread.h>

#define KEY 0x1234

#define NUMTHREADS 2

void *retval[NUMTHREADS]; 
void * waiter(void *);
void * poster(void *);

struct sembuf Psembuf = {0, -1, SEM_UNDO};
struct sembuf Vsembuf = {0, 1, SEM_UNDO};

int sem_id;

main()
{
    int i, pid, rc;
    
    pthread_t pt[NUMTHREADS];
    pthread_attr_t attr;

    /* Create the semaphore set */
    sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
    if (sem_id < 0)
    {
	printf ("semget failed, errno = %d\n", errno);
	exit (1);
    }
    
    /* setup the attributes of the thread        */
    /* set the scope to be system to make sure the process competes on a  */
    /* global scale for cpu   */
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    /* Create the threads */
    for (i=0; i<NUMTHREADS; i++)
    {
	if (i == 0)
	    rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
	else
	    rc = pthread_create(&pt[i], &attr, poster, retval[i]);
    }

    /* Sleep long enough to see that the other threads do what they are supposed to do */
    sleep(20);

    exit(0);
}


/* This thread sleeps 10 seconds then waits on the semaphore.  As long
   as someone has posted on the semaphore, and no undo has taken
   place, the semop should complete and we'll print "Waiter done
   waiting." */
void * waiter(void * foo)
{
    int pid;
    pid = getpid();

    printf ("Waiter, pid = %d\n", pid);
    sleep(10);

    printf("Waiter waiting, pid = %d\n", pid);
    semop(sem_id, &Psembuf, 1);
    printf("Waiter done waiting\n");
   
    pthread_exit(0);
}

/* This thread immediately posts on the semaphore and then immediately
   exits.  If the *thread* exits, the undo should not happen, and the
   waiter thread which will start waiting on it in 10 seconds, should
   still get it.   */
void * poster(void * foo)
{
    int pid;
   
    pid = getpid();
    printf ("Poster, pid = %d, posting\n", pid);
    semop(sem_id, &Vsembuf, 1);
    printf ("Poster posted\n");
    printf ("Poster exiting\n");
    
    pthread_exit(0);
}

------------------------Begin Patch for linux 2.4.17-------------------------


diff -urN --exclude-from=/usr/src/dontdiff linux-2.4.17_original/linux/include/linux/sched.h linux-2.4.17_SEMUNDO/linux/include/linux/sched.h
--- linux-2.4.17_original/linux/include/linux/sched.h	Fri Dec 21 09:42:03 2001
+++ linux-2.4.17_SEMUNDO/linux/include/linux/sched.h	Mon Jan 21 19:12:35 2002
@@ -381,7 +381,7 @@
 	struct tty_struct *tty; /* NULL if no tty */
 	unsigned int locks; /* How many file locks are being held */
 /* ipc stuff */
-	struct sem_undo *semundo;
+	struct sem_undohd *semundohd;
 	struct sem_queue *semsleeping;
 /* CPU-specific state of this task */
 	struct thread_struct thread;
diff -urN --exclude-from=/usr/src/dontdiff linux-2.4.17_original/linux/include/linux/sem.h linux-2.4.17_SEMUNDO/linux/include/linux/sem.h
--- linux-2.4.17_original/linux/include/linux/sem.h	Thu Nov 22 11:46:18 2001
+++ linux-2.4.17_SEMUNDO/linux/include/linux/sem.h	Mon Jan 21 19:12:35 2002
@@ -121,6 +121,18 @@
 	short *			semadj;		/* array of adjustments, one per semaphore */
 };
 
+/* Each PROCESS (i.e. collection of tasks that are running POSIX style threads)
+ * must share the same semundo list, in order to support POSIX SEMUNDO
+ * semantics for threads.  The sem_undohd controls shared access to this
+ * list among all the tasks (threads) in that process.
+ */ 
+struct sem_undohd {
+	atomic_t	refcnt;
+	spinlock_t	lock;
+	volatile unsigned long	add_count;
+	struct sem_undo	*proc_list;
+};
+
 asmlinkage long sys_semget (key_t key, int nsems, int semflg);
 asmlinkage long sys_semop (int semid, struct sembuf *sops, unsigned nsops);
 asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg);
diff -urN --exclude-from=/usr/src/dontdiff linux-2.4.17_original/linux/ipc/sem.c linux-2.4.17_SEMUNDO/linux/ipc/sem.c
--- linux-2.4.17_original/linux/ipc/sem.c	Sun Sep 30 12:26:42 2001
+++ linux-2.4.17_SEMUNDO/linux/ipc/sem.c	Mon Jan 21 19:08:05 2002
@@ -788,12 +788,75 @@
 	}
 }
 
-static struct sem_undo* freeundos(struct sem_array *sma, struct sem_undo* un)
+static inline void lock_semundo(void)
+{
+	struct sem_undohd *undohd;
+
+	undohd = current->semundohd;
+	if ((undohd != NULL) && (atomic_read(&undohd->refcnt) != 1))
+		spin_lock(&undohd->lock);
+}
+
+/* This code has an interesting interaction with copy_semundo():
+ * two tasks could have been sharing the semundohd at the time "first" one
+ * of those tasks acquires the lock acquired in lock_semundo.  If the other
+ * tasks exits before * "the first one" releases the lock (by calling
+ * unlock_semundo), then the spin_unlock would NOT be called.  This would
+ * leave the semundohd in a locked state.  This would NOT be a problem unless
+ * the remaining task once again creates a new task that once again shares the
+ * semundohd.  Cleanup up this last case is dealt with in copy_semundo by
+ * having it reinitialize the spin_lock when it once again creates a second
+ * task sharing the semundo.
+ */
+static inline void unlock_semundo(void)
+{
+	struct sem_undohd *undohd;
+
+	undohd = current->semundohd;
+	if ((undohd != NULL) && (atomic_read(&undohd->refcnt) != 1))
+		spin_unlock(&undohd->lock);
+}
+
+
+/* If the task doesn't already have a semundohd, then allocate one
+ * here.  We guarantee there is only one thread using this undo list,
+ * and current is THE ONE
+ *
+ * If this allocation and assignment succeeds, but later
+ * portions of this code fail, there is no need to free the sem_undohd.
+ * Just let it stay associated with the task, and it'll be freed later
+ * at exit time.
+ *
+ * This can block, so callers must hold no locks.
+ */
+static inline int get_undohd(struct sem_undohd **undohdp)
+{
+	struct sem_undohd *undohd;
+	int size;
+
+	undohd = current->semundohd;
+	if (!undohd) {
+		size = sizeof(struct sem_undohd);
+		undohd = (struct sem_undohd *) kmalloc(size, GFP_KERNEL);
+		if (undohd == NULL)
+			return -ENOMEM;
+		memset(undohd, 0, size);
+		/* don't initialize unodhd->lock here.  It's done
+		 * in copy_semundo() instead.
+		 */
+		atomic_set(&undohd->refcnt, 1);
+		current->semundohd = undohd;
+	}
+	*undohdp = undohd;
+	return 0;
+}
+
+static struct sem_undo* freeundos(struct sem_undo* un)
 {
 	struct sem_undo* u;
 	struct sem_undo** up;
 
-	for(up = &current->semundo;(u=*up);up=&u->proc_next) {
+	for(up = &current->semundohd->proc_list;(u=*up);up=&u->proc_next) {
 		if(un==u) {
 			un=u->proc_next;
 			*up=un;
@@ -805,33 +868,87 @@
 	return un->proc_next;
 }
 
-/* returns without sem_lock on error! */
+static inline struct sem_undo *find_undo(int semid)
+{
+	struct sem_undo *un;
+
+	un = NULL;
+	if (current->semundohd != NULL) {
+		un = current->semundohd->proc_list;
+	}
+	while(un != NULL) {
+		if(un->semid==semid)
+			break;
+		if(un->semid==-1)
+			un=freeundos(un);
+		 else
+			un=un->proc_next;
+	}
+	return un;
+}
+
+/* returns without sem_lock and semundo list locks on error! */
 static int alloc_undo(struct sem_array *sma, struct sem_undo** unp, int semid, int alter)
 {
 	int size, nsems, error;
-	struct sem_undo *un;
+	struct sem_undo *un, *new_un;
+	struct sem_undohd *unhd;
+	unsigned long	saved_add_count;
+
 
 	nsems = sma->sem_nsems;
-	size = sizeof(struct sem_undo) + sizeof(short)*nsems;
+	saved_add_count = 0;
+	if (current->semundohd != NULL)
+		saved_add_count = current->semundohd->add_count;
 	sem_unlock(semid);
+	unlock_semundo();
 
+	error = get_undohd(&unhd);
+	if (error)
+		return error;
+
+	size = sizeof(struct sem_undo) + sizeof(short)*nsems;
 	un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
 	if (!un)
 		return -ENOMEM;
 
 	memset(un, 0, size);
+	lock_semundo();
 	error = sem_revalidate(semid, sma, nsems, alter ? S_IWUGO : S_IRUGO);
 	if(error) {
+		unlock_semundo();
 		kfree(un);
 		return error;
 	}
 
-	un->semadj = (short *) &un[1];
-	un->semid = semid;
-	un->proc_next = current->semundo;
-	current->semundo = un;
-	un->id_next = sma->undo;
-	sma->undo = un;
+
+	/* alloc_undo has just
+	 * released all locks and reacquired them. 
+	 * But, another thread may have
+	 * added the semundo we were looking for
+	 * during that time.
+	 * So, we check for it again.
+	 * only initialize and add the new one
+	 * if we don't discover one.
+	 */
+	new_un = NULL;
+	if (current->semundohd->add_count != saved_add_count)
+		new_un = find_undo(semid);
+
+	if (new_un != NULL) {
+		if (sma->undo != new_un)
+			BUG();
+		kfree(un);
+		un = new_un;
+	} else {
+		current->semundohd->add_count++;
+		un->semadj = (short *) &un[1];
+		un->semid = semid;
+		un->proc_next = unhd->proc_list;
+		unhd->proc_list = un;
+		un->id_next = sma->undo;
+		sma->undo = un;
+	}
 	*unp = un;
 	return 0;
 }
@@ -846,6 +963,7 @@
 	int undos = 0, decrease = 0, alter = 0;
 	struct sem_queue queue;
 
+
 	if (nsops < 1 || semid < 0)
 		return -EINVAL;
 	if (nsops > sc_semopm)
@@ -859,17 +977,18 @@
 		error=-EFAULT;
 		goto out_free;
 	}
+	lock_semundo();
 	sma = sem_lock(semid);
 	error=-EINVAL;
 	if(sma==NULL)
-		goto out_free;
+		goto out_semundo_free;
 	error = -EIDRM;
 	if (sem_checkid(sma,semid))
-		goto out_unlock_free;
+		goto out_unlock_semundo_free;
 	error = -EFBIG;
 	for (sop = sops; sop < sops + nsops; sop++) {
 		if (sop->sem_num >= sma->sem_nsems)
-			goto out_unlock_free;
+			goto out_unlock_semundo_free;
 		if (sop->sem_flg & SEM_UNDO)
 			undos++;
 		if (sop->sem_op < 0)
@@ -881,24 +1000,18 @@
 
 	error = -EACCES;
 	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-		goto out_unlock_free;
+		goto out_unlock_semundo_free;
 	if (undos) {
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
 		 */
-		un=current->semundo;
-		while(un != NULL) {
-			if(un->semid==semid)
-				break;
-			if(un->semid==-1)
-				un=freeundos(sma,un);
-			 else
-				un=un->proc_next;
-		}
+		
+		un = find_undo(semid);
 		if (!un) {
 			error = alloc_undo(sma,&un,semid,alter);
-			if(error)
+			if (error)
 				goto out_free;
+
 		}
 	} else
 		un = NULL;
@@ -930,16 +1043,18 @@
 		queue.sleeper = current;
 		current->state = TASK_INTERRUPTIBLE;
 		sem_unlock(semid);
+		unlock_semundo();
 
 		schedule();
 
+		lock_semundo();
 		tmp = sem_lock(semid);
 		if(tmp==NULL) {
 			if(queue.prev != NULL)
 				BUG();
 			current->semsleeping = NULL;
 			error = -EIDRM;
-			goto out_free;
+			goto out_semundo_free;
 		}
 		/*
 		 * If queue.status == 1 we where woken up and
@@ -960,7 +1075,7 @@
 				break;
 			/* Everything done by update_queue */
 			current->semsleeping = NULL;
-			goto out_unlock_free;
+			goto out_unlock_semundo_free;
 		}
 	}
 	current->semsleeping = NULL;
@@ -968,14 +1083,61 @@
 update:
 	if (alter)
 		update_queue (sma);
-out_unlock_free:
+out_unlock_semundo_free:
 	sem_unlock(semid);
+out_semundo_free:
+	unlock_semundo();
 out_free:
 	if(sops != fast_sops)
 		kfree(sops);
 	return error;
 }
 
+/* For now, assume that if ALL clone flags are set, then
+ * we must be creating a POSIX thread, and we want undo lists
+ * to be shared among all the threads in that thread group.
+ *
+ * See the notes above unlock_semundo() regarding the spin_lock_init()
+ * in this code.  Initialize the undohd->lock here instead of get_undohd()
+ * because of the reasoning in the note referenced here.
+ */
+#define CLONE_SEMUNDO (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND)
+
+int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
+{
+	struct sem_undohd *undohd;
+	int error;
+
+	if (((clone_flags & CLONE_SEMUNDO) == CLONE_SEMUNDO) ||
+		(clone_flags & CLONE_THREAD)) {
+		error = get_undohd(&undohd);
+		if (error)
+			return error;
+		if (atomic_read(&undohd->refcnt) == 1)
+			spin_lock_init(&undohd->lock);
+		atomic_inc(&undohd->refcnt);
+		tsk->semundohd = undohd;
+	} else 
+		tsk->semundohd = NULL;
+
+	return 0;
+}
+
+static inline void __exit_semundo(struct task_struct *tsk)
+{
+	struct sem_undohd *unhd;
+
+	unhd = tsk->semundohd;
+	if (!atomic_dec_and_test(&unhd->refcnt))
+		kfree(unhd);
+}
+
+void exit_semundo(struct task_struct *tsk)
+{
+	if (tsk->semundohd != NULL)
+		__exit_semundo(tsk);
+}
+
 /*
  * add semadj values to semaphores, free undo structures.
  * undo structures are not freed when semaphore arrays are destroyed
@@ -993,6 +1155,7 @@
 	struct sem_queue *q;
 	struct sem_undo *u, *un = NULL, **up, **unp;
 	struct sem_array *sma;
+	struct sem_undohd *undohd;
 	int nsems, i;
 
 	/* If the current process was sleeping for a semaphore,
@@ -1012,7 +1175,14 @@
 			sem_unlock(semid);
 	}
 
-	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
+	undohd = current->semundohd;
+	if ((undohd == NULL) || (atomic_read(&undohd->refcnt) != 1))
+		return;
+
+	/* There's no need to hold the semundo list lock, as current
+         * is the last task exiting for this undo list.
+	 */
+	for (up = &undohd->proc_list; (u = *up); *up = u->proc_next, kfree(u)) {
 		int semid = u->semid;
 		if(semid == -1)
 			continue;
@@ -1050,7 +1220,7 @@
 next_entry:
 		sem_unlock(semid);
 	}
-	current->semundo = NULL;
+	__exit_semundo(current);
 }
 
 #ifdef CONFIG_PROC_FS
diff -urN --exclude-from=/usr/src/dontdiff linux-2.4.17_original/linux/ipc/util.c linux-2.4.17_SEMUNDO/linux/ipc/util.c
--- linux-2.4.17_original/linux/ipc/util.c	Sun Aug 12 17:37:53 2001
+++ linux-2.4.17_SEMUNDO/linux/ipc/util.c	Mon Jan 21 19:08:05 2002
@@ -340,6 +340,17 @@
  * Dummy functions when SYSV IPC isn't configured
  */
 
+int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
+{
+	return 0;
+}
+
+void exit_semundo(struct task_struct *tsk)
+{
+	return;
+}
+
+
 void sem_exit (void)
 {
     return;
diff -urN --exclude-from=/usr/src/dontdiff linux-2.4.17_original/linux/kernel/fork.c linux-2.4.17_SEMUNDO/linux/kernel/fork.c
--- linux-2.4.17_original/linux/kernel/fork.c	Wed Nov 21 10:18:42 2001
+++ linux-2.4.17_SEMUNDO/linux/kernel/fork.c	Mon Jan 21 19:08:05 2002
@@ -26,6 +26,9 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
+extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk);
+extern void exit_semundo(struct task_struct *tsk);
+
 /* The idle threads do not count.. */
 int nr_threads;
 int nr_running;
@@ -653,8 +656,10 @@
 
 	retval = -ENOMEM;
 	/* copy all the process information */
-	if (copy_files(clone_flags, p))
+	if (copy_semundo(clone_flags, p))
 		goto bad_fork_cleanup;
+	if (copy_files(clone_flags, p))
+		goto bad_fork_cleanup_semundo;
 	if (copy_fs(clone_flags, p))
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
@@ -664,7 +669,6 @@
 	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
 		goto bad_fork_cleanup_mm;
-	p->semundo = NULL;
 	
 	/* Our parent execution domain becomes current domain
 	   These must match for thread signalling to apply */
@@ -738,6 +742,8 @@
 	exit_fs(p); /* blocking */
 bad_fork_cleanup_files:
 	exit_files(p); /* blocking */
+bad_fork_cleanup_semundo:
+	exit_semundo(p);
 bad_fork_cleanup:
 	put_exec_domain(p->exec_domain);
 	if (p->binfmt && p->binfmt->module)

^ permalink raw reply

* Re: Conflicts between network and Matrox G450
From: hollis @ 2002-01-22 18:39 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20020122152500.GF510@austin.ibm.com>


Sorry, the patch was too large to post and is located for the moment at
http://penguinppc.org/~hollis/matroxfb-20020108.diff

-Hollis

On Tue, Jan 22, 2002 at 09:25:00AM -0600, hollis@austin.ibm.com wrote:
> On Tue, Jan 22, 2002 at 03:02:34PM +0100, Jan Smith wrote:
> >
> > I have a IBM pSeries 610 where I try to install a Matrox G450 card
> > aka GXT130P in IBM language.
>
> The GXT130P is actually a G400. The G450 is the GXT135P.
>
> > The machine is working fine with a RedHat Linux run via a terminal
> > but when you are using the graphics card will the network interface
> > not start at all.
>
> Have you compared the boot logs from a working boot and a failed boot?
>
> > Any one who have used a Matrox G450 with ppclinux?
>
> I think the G400 is supposed to work with matroxfb on PPC (though I've never
> tested nor heard reports one way or the other). If you really do have a G450,
> that's problematic. With the attached patch (submitted to Marcelo recently; I
> don't know if it was applied), I experienced success exactly once. OTOH, Olaf
> said it worked for him every time. Your mileage may vary. Please provide
> feedback to the matroxfb maintainer (Petr Vandrovec <vandrove@vc.cvut.cz>) if
> it works or not.
>
> -Hollis

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply

* Re: thread-ready ABIs
From: Ulrich Drepper @ 2002-01-22 17:41 UTC (permalink / raw)
  To: Dominic Sweetman
  Cc: Kevin D. Kissell, Ralf Baechle, Mike Uhler, linux-mips,
	H . J . Lu
In-Reply-To: <15437.13028.496595.150427@gladsmuir.algor.co.uk>

Dominic Sweetman <dom@algor.co.uk> writes:

> Sometimes when you're busy it's understandable to respond with "RTFM".
> But to fail to provide a URL is not very respectful: other people
> reading this list are quite smart, they're just smart about different
> things from you.

A simple Google search would have turned up

  http://developer.intel.com/design/itanium/downloads/24537003.pdf

as the first choice.  Section 7.5.

-- 
---------------.                          ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Red Hat          `--' drepper at redhat.com   `------------------------

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.