(no subject)

2005-08-04 Thread Felix-KM
Hello.
Help me please to understand how the function bus_teardown_intr() works.
I have a device driver containing following code:

#define DEVICE2SOFTC(device) ((struct dev_softc *)device_get_softc(device))

static void dev_intr(void *arg);

struct dev_softc {
  ...
  int rid_irq;
  struct resource* res_irq;
  void  *intr_cookie;
  ...
};

static int
dev_attach(device_t device)
{
  ...
  
  dev_sc-rid_irq = 0;
  dev_sc-res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
 (dev_sc-rid_irq), RF_SHAREABLE|RF_ACTIVE);
  if (dev_sc-res_irq == NULL)
  {
uprintf(!!! Could not map interrupt !!!\n);
goto fail;
  }
  
  if (bus_setup_intr(device, dev_sc-res_irq, INTR_TYPE_TTY,
 dev_intr, dev_sc, dev_sc-intr_cookie))
  {
uprintf(!!! Could not setup irq !!!\n);
goto fail;
  } 
  
  ...
  
fail:
  return ENXIO;
}

static int
dev_detach(device_t device)
{
  struct dev_softc *dev_sc = DEVICE2SOFTC(device);

  destroy_dev(dev_sc-device);

  if (bus_teardown_intr(device, dev_sc-res_irq, dev_sc-intr_cookie) != 0);
printf(bus_teardown_intr ERROR !!!\n);
  
  bus_release_resource(device, SYS_RES_IRQ, dev_sc-rid_irq,
dev_sc-res_irq);
...

  return 0;
}

static void
dev_intr(void *arg)
{
  struct dev_softc *dev_sc = (struct dev_softc *)arg;

  ...
}

When the driver is loaded the following message is shown:

dev0 port 0x9800-0x980f,0x9400-0x947f irq 16 at device 10.0 on pci1

i.e., as I understand, resourses are allocated normally.

But when the driver is being unloaded the following message appear:

bus_teardown_intr ERROR !!!

What have I done wrong? Hint me please how to use bus_teardown_intr()
function correctly?
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


bus_teardown_intr()

2005-08-04 Thread Felix-KM
Sorry, I forgot to indicate the theme.
Hello.
Help me please to understand how the function bus_teardown_intr() works.
I have a device driver containing following code:

#define DEVICE2SOFTC(device) ((struct dev_softc *)device_get_softc(device))

static void dev_intr(void *arg);

struct dev_softc {
  ...
  int rid_irq;
  struct resource* res_irq;
  void *intr_cookie;
  ...
};

static int
dev_attach(device_t device)
{
  ...
  
  dev_sc-rid_irq = 0;
  dev_sc-res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
 (dev_sc-rid_irq), RF_SHAREABLE|RF_ACTIVE);
  if (dev_sc-res_irq == NULL)
  {
uprintf(!!! Could not map interrupt !!!\n);
goto fail;
  }
  
  if (bus_setup_intr(device, dev_sc-res_irq, INTR_TYPE_TTY,
 dev_intr, dev_sc, dev_sc-intr_cookie))
  {
uprintf(!!! Could not setup irq !!!\n);
goto fail;
  }
  
  ...
  
fail:
  return ENXIO;
}

static int
dev_detach(device_t device)
{
  struct dev_softc *dev_sc = DEVICE2SOFTC(device);

  destroy_dev(dev_sc-device);

  if (bus_teardown_intr(device, dev_sc-res_irq, dev_sc-intr_cookie) != 0);
printf(bus_teardown_intr ERROR !!!\n);
  
  bus_release_resource(device, SYS_RES_IRQ, dev_sc-rid_irq,
dev_sc-res_irq);
   ...
   
  return 0;
}

static void
dev_intr(void *arg)
{
  struct dev_softc *dev_sc = (struct dev_softc *)arg;

  ...
}

When the driver is loaded the following message is shown:

dev0 port 0x9800-0x980f,0x9400-0x947f irq 16 at device 10.0 on pci1

i.e., as I understand, resourses are allocated normally.

But when the driver is being unloaded the following message appear:

bus_teardown_intr ERROR !!!

What have I done wrong? Hint me please how to use bus_teardown_intr()
function correctly?
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


-- 
Яндекс.Лента - любимые блоги и новости на одном сайте http://lenta.yandex.ru/
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: (no subject)

2005-08-04 Thread Norbert Koch
 #define DEVICE2SOFTC(device) ((struct dev_softc
 *)device_get_softc(device))

 static void dev_intr(void *arg);

 struct dev_softc {
   ...
   int rid_irq;
   struct resource* res_irq;
   void*intr_cookie;
   ...
 };

 static int
 dev_attach(device_t device)
 {
   ...

   dev_sc-rid_irq = 0;
   dev_sc-res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
  (dev_sc-rid_irq),
 RF_SHAREABLE|RF_ACTIVE);
   if (dev_sc-res_irq == NULL)
   {
 uprintf(!!! Could not map interrupt !!!\n);
 goto fail;
   }

   if (bus_setup_intr(device, dev_sc-res_irq, INTR_TYPE_TTY,
  dev_intr, dev_sc, dev_sc-intr_cookie))
   {
 uprintf(!!! Could not setup irq !!!\n);
 goto fail;
   }

   ...

 fail:
   return ENXIO;
 }

 static int
 dev_detach(device_t device)
 {
   struct dev_softc *dev_sc = DEVICE2SOFTC(device);

   destroy_dev(dev_sc-device);

   if (bus_teardown_intr(device, dev_sc-res_irq,
 dev_sc-intr_cookie) != 0);

 Do you see that semicolon? 


Norbert



 printf(bus_teardown_intr ERROR !!!\n);

   bus_release_resource(device, SYS_RES_IRQ, dev_sc-rid_irq,

 dev_sc-res_irq);
   ...

   return 0;
 }

 static void
 dev_intr(void *arg)
 {
   struct dev_softc *dev_sc = (struct dev_softc *)arg;

   ...
 }

 When the driver is loaded the following message is shown:

 dev0 port 0x9800-0x980f,0x9400-0x947f irq 16 at device 10.0 on pci1

 i.e., as I understand, resourses are allocated normally.

 But when the driver is being unloaded the following message appear:

 bus_teardown_intr ERROR !!!

 What have I done wrong? Hint me please how to use bus_teardown_intr()
 function correctly?
 ___
 freebsd-hackers@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
 To unsubscribe, send any mail to [EMAIL PROTECTED]


___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: (no subject)

2005-08-04 Thread Felix-KM
 #define DEVICE2SOFTC(device) ((struct dev_softc
 *)device_get_softc(device))

 static void dev_intr(void *arg);

 struct dev_softc {
   ...
   int rid_irq;
   struct resource* res_irq;
   void   *intr_cookie;
   ...
 };

 static int
 dev_attach(device_t device)
 {
   ...

   dev_sc-rid_irq = 0;
   dev_sc-res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ,
  (dev_sc-rid_irq),
 RF_SHAREABLE|RF_ACTIVE);
   if (dev_sc-res_irq == NULL)
   {
 uprintf(!!! Could not map interrupt !!!\n);
 goto fail;
   }

   if (bus_setup_intr(device, dev_sc-res_irq, INTR_TYPE_TTY,
  dev_intr, dev_sc, dev_sc-intr_cookie))
   {
 uprintf(!!! Could not setup irq !!!\n);
 goto fail;
   }

   ...

 fail:
   return ENXIO;
 }

 static int
 dev_detach(device_t device)
 {
   struct dev_softc *dev_sc = DEVICE2SOFTC(device);

   destroy_dev(dev_sc-device);

   if (bus_teardown_intr(device, dev_sc-res_irq,
 dev_sc-intr_cookie) != 0);

 Do you see that semicolon? 


Norbert


Oops...  I am ashamed for my inattention...
Thank you very much...
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: How to do proper locking

2005-08-04 Thread Hans Petter Selasky
On Wednesday 03 August 2005 19:21, John Baldwin wrote:
 On Tuesday 02 August 2005 06:23 pm, Hans Petter Selasky wrote:
  Hi,
 
  I am looking for a safe way to access structures that can be freed. The
  solution I am looking for must not:
 
  - hinder scaleability
  - lead to use of a single lock
  - lead to lock order reversal

There is one more thing. When the structure is freed it should not block 
waiting for any reference counts.


 These aren't a very clear set of requirements. 

If you think about the situation of accessing a structure in parallell with 
freeing it, and want to do it 100 percent safe, you will see that you have to 
do some kind of test before accessing this structure to see if it is still 
present. So how should this test look like if you want to keep the points 
I've listed above in mind?

 Note that you can't hold a 
 lock across malloc(), so your allocation code isn't safe. 

I was thinking that the M_NOWAIT flag was passed malloc(). Else in this case, 
I think it is safe to unlock/lock lock_A when malloc is called.

 You can try taking at look at some existing refcounted structures such 
 as ucreds, p_args, etc. or looking at structures held in a global list 
 like proc.  

It looks to me like some parent lock is held, or that these structures are 
only accessed from a single thread, to prevent synchronization problems.

This is a copy and paste from the kernel sources:

struct ucred *
crhold(struct ucred *cr)
{
The problem is, what happens if the kernel switches thread right here, and 
then the other thread calls crfree() on this structure, that will free() 
memory pointed to by cr. Then the first line of code below will access 
freed memory, and then we are going for a segment fault or worse.

mtx_lock(cr-cr_mtxp);
cr-cr_ref++;
mtx_unlock(cr-cr_mtxp);
return (cr);
}

So this is what I want this routine and alike to look like:

struct cr_callback_args {
  struct ucred *cr;
  struct mtx *p_mtx;
  u_int32_t refcount_copy,
  u_int32_t *p_refcount;
};

struct ucred *
crhold(struct cr_ballback_args *args)
{
  mtx_lock(args-p_mtx);
  if(args-refcount_copy == ref_atomic_read(args-p_refcount))
  {
/* the structure pointed to by args-cr is still valid */

/* maybe we don't need the refcount below, but instead
 * can return with this structure locked, hence the 
 * reference count will be incremented before 
 * args-cr is freed, and after that the test
 * above will fail.
 */
args-cr-cr_ref++;
  }
  mtx_lock(args-p_mtx);
  return (args-cr);
}

 What actual problem are you trying to solve?  

Generic callbacks:

- setting up timers. Make sure that callback is never called after that timer 
has been stopped.

- setting up devices. Make sure that read/write/ioctl/poll callbacks are never 
called after that the device has been freed.

- setting up interrupts. Make sure that interrupt routine is never called 
after that it is been teared down.


And more. There are lots of situations in the kernel that run into the same 
scheme, without a proper solution.


In my initial suggestion, I suggested that there be a ref_atomic_increment() 
routine, but I think it is better without. Then every time one needs to 
increment the refcount, one has to go through a ref_free/ref_alloc loop. The 
idea is that ref_free() will detect when the refcount is equal to 
(u_int32_t)(-1) and put the refount on a trash list. Then ideally one never 
recycles used up refcounts.


 How does code obtain references to my_struct objects? 

For example when you set up a timer, you pass the pointer to the structure 
that the callback is going to access.

struct my_struct *sc = ...;

callout_reset(callback, 1*hz, my_callback, sc);


 Are they hung off another object that has 
 a lock? 

Usually, but the parent lock cannot help much.

 Are they in a global list? 

Yes and no. Sometimes these structures have roots in structures that are freed 
too, in the same manner, but at the bottom there is a static and global list. 
Was this what you meant?


-- HPS
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: How to do proper locking

2005-08-04 Thread Max Laier
On Thursday 04 August 2005 13:40, Hans Petter Selasky wrote:
 This is a copy and paste from the kernel sources:

 struct ucred *
 crhold(struct ucred *cr)
 {
 The problem is, what happens if the kernel switches thread right here, and
 then the other thread calls crfree() on this structure, that will
 free() memory pointed to by cr. Then the first line of code below will
 access freed memory, and then we are going for a segment fault or worse.

 mtx_lock(cr-cr_mtxp);
 cr-cr_ref++;
 mtx_unlock(cr-cr_mtxp);
 return (cr);
 }

It seems that you are misunderstanding the concept of reference counting.  The 
idea is to have a reference as long as you are handing around the object.  In 
order to call crhold() you must already hold a reference to the credential.  
This will prevent the credential structure to vanish and allow you to pass 
the credential to another consumer that now can assume to hold a reference of 
it's own.

If you can access your objects from a external list, you have to hold a global 
lock that protects:
 1) Sanity of the list
 2) Free operations to the member objects

If you access the objects via the list/tree/whatsoever most of the time - 
refcounting isn't for you.

-- 
/\  Best regards,  | [EMAIL PROTECTED]
\ /  Max Laier  | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | [EMAIL PROTECTED]
/ \  ASCII Ribbon Campaign  | Against HTML Mail and News


pgpH6ellm2xb0.pgp
Description: PGP signature


Sub-optimal libc's read-ahead buffering behaviour

2005-08-04 Thread Maxim Sobolev

Hi,

I have found the scenario in which our libc behaves utterly 
suboptimally. Consider the following piece of code reads and processes 
every other 512-bytes block in a file (error handling intentionally 
omitted):


FILE *f;
int i;
char buf[512];

f = fopen(...);
for (i = 0; feof(f) == 0; i++) {
  fread(buf, sizeof(buf), 1, f);
  do_process(buf);
  fseek(f, i * 2 * sizeof(buf), SEEK_SET);
}

What I have discovered in this case is that libc reads 4096 bytes from 
the file for *each* fread(3) call, despite the fact that it can only do 
one actual read(2) for every fourth fread(3) and satisfy the rest from 
the internal buffer (4096 bytes). However, if I replace fseek(3) with 
just another dummy fread(3) everything works as expected - libc does 
only one read for every 8 fread(3) calls (4 dummy and 4 real).


Is it something which should be fixed or are there some subtle reasons 
for the current behaviour?


Following is piece of code which illustrates the problem:

#include stdio.h
#include stdlib.h

int
main(int argc, char **argv)
{
FILE *f;
int i;
char buf[512];

f = fopen(/dev/zero, r);
for (i = 0; i  16; i++) {
fread(buf, sizeof(buf), 1, f);
if (argc == 1)
fread(buf, sizeof(buf), 1, f);
else
fseek(f, i * 2 * sizeof(buf), SEEK_SET);
}
exit(0);
}

When run with zero arguments relevant truss output looks like:

open(/dev/zero,0x0,0666)   = 3 (0x3)
fstat(3,0xbfbfe900)  = 0 (0x0)
readlink(/etc/malloc.conf,0xbfbfe8c0,63)   ERR#2 'No such file or 
directory'

issetugid()  = 0 (0x0)
mmap(0x0,4096,(0x3)PROT_READ|PROT_WRITE,(0x1002)MAP_ANON|MAP_PRIVATE,-1,0x0) 
= 1209335808 (0x4815)

break(0x804b000) = 0 (0x0)
break(0x804c000) = 0 (0x0)
ioctl(3,TIOCGETA,0xbfbfe940) ERR#19 'Operation not 
supported by device'

read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
exit(0x0)

While when I am specifying some argument it becomes:

open(/dev/zero,0x0,0666)   = 3 (0x3)
fstat(3,0xbfbfe900)  = 0 (0x0)
readlink(/etc/malloc.conf,0xbfbfe8c0,63)   ERR#2 'No such file or 
directory'

issetugid()  = 0 (0x0)
mmap(0x0,4096,(0x3)PROT_READ|PROT_WRITE,(0x1002)MAP_ANON|MAP_PRIVATE,-1,0x0) 
= 1209335808 (0x4815)

break(0x804b000) = 0 (0x0)
break(0x804c000) = 0 (0x0)
ioctl(3,TIOCGETA,0xbfbfe940) ERR#19 'Operation not 
supported by device'

read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x0,SEEK_SET)= 0 (0x0)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x400,SEEK_SET)  = 1024 (0x400)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x800,SEEK_SET)  = 2048 (0x800)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0xc00,SEEK_SET)  = 3072 (0xc00)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x1000,SEEK_SET) = 4096 (0x1000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x1400,SEEK_SET) = 5120 (0x1400)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x1800,SEEK_SET) = 6144 (0x1800)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x1c00,SEEK_SET) = 7168 (0x1c00)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x2000,SEEK_SET) = 8192 (0x2000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x2400,SEEK_SET) = 9216 (0x2400)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x2800,SEEK_SET) = 10240 (0x2800)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x2c00,SEEK_SET) = 11264 (0x2c00)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x3000,SEEK_SET) = 12288 (0x3000)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x3400,SEEK_SET) = 13312 (0x3400)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x3800,SEEK_SET) = 14336 (0x3800)
read(0x3,0x804b000,0x1000)   = 4096 (0x1000)
lseek(3,0x3c00,SEEK_SET) = 15360 (0x3c00)
exit(0x0)

The output speaks for 

Re: How to do proper locking

2005-08-04 Thread John Baldwin
On Thursday 04 August 2005 07:40 am, Hans Petter Selasky wrote:
 On Wednesday 03 August 2005 19:21, John Baldwin wrote:
  On Tuesday 02 August 2005 06:23 pm, Hans Petter Selasky wrote:
   Hi,
  
   I am looking for a safe way to access structures that can be freed. The
   solution I am looking for must not:
  
   - hinder scaleability
   - lead to use of a single lock
   - lead to lock order reversal

 There is one more thing. When the structure is freed it should not block
 waiting for any reference counts.

  These aren't a very clear set of requirements.

 If you think about the situation of accessing a structure in parallell with
 freeing it, and want to do it 100 percent safe, you will see that you have
 to do some kind of test before accessing this structure to see if it is
 still present. So how should this test look like if you want to keep the
 points I've listed above in mind?

  Note that you can't hold a
  lock across malloc(), so your allocation code isn't safe.

 I was thinking that the M_NOWAIT flag was passed malloc(). Else in this
 case, I think it is safe to unlock/lock lock_A when malloc is called.

  You can try taking at look at some existing refcounted structures such
  as ucreds, p_args, etc. or looking at structures held in a global list
  like proc.

 It looks to me like some parent lock is held, or that these structures are
 only accessed from a single thread, to prevent synchronization problems.

You hold a parent lock (which is what your lock_A is if you think about it) 
while you bump the reference count, yes.

 This is a copy and paste from the kernel sources:

 struct ucred *
 crhold(struct ucred *cr)
 {
 The problem is, what happens if the kernel switches thread right here, and
 then the other thread calls crfree() on this structure, that will
 free() memory pointed to by cr. Then the first line of code below will
 access freed memory, and then we are going for a segment fault or worse.

 mtx_lock(cr-cr_mtxp);
 cr-cr_ref++;
 mtx_unlock(cr-cr_mtxp);
 return (cr);
 }

crhold() is always called when the caller knows that it has a reference to cr 
that can't go away.  Thus, in the case of p_ucred, one holds the associated 
PROC_LOCK() while doing crhold().  After the crhold() you can drop the proc 
lock, so that lock is only held for a very short period of time.  You then 
have your own reference to the cred structure that is valid until you call 
crfree().  In the case of curthread-td_ucred, the reference is valid until 
curthread releases it on a cred update at the start of a syscall, so your 
reference is valid without needing locks for the life of a syscall.  The key 
here is that you solve this problem at a higher level, not within the 
structure itself.

  What actual problem are you trying to solve?

 Generic callbacks:

 - setting up timers. Make sure that callback is never called after that
 timer has been stopped.

See callout_stop() and callout_drain().  callout_drain() won't return until 
the callout has both been stopped and has finished executing if it was 
already in progress.

 - setting up devices. Make sure that read/write/ioctl/poll callbacks are
 never called after that the device has been freed.

This is managed with refcounts on the dev_t object by devfs.  Once you call 
destroy_dev() devfs manages the rest.

 - setting up interrupts. Make sure that interrupt routine is never called
 after that it is been teared down.

bus_teardown_intr() already does this.

 And more. There are lots of situations in the kernel that run into the same
 scheme, without a proper solution.

Are there any other places you can think of that don't handle this already?  
The approach FreeBSD's kernel has taken is to solve this problem by 
duplicating a lot of checks all over the place for each data structure, but 
to solve it in the primitives themselves instead (hence callout_drain(), 
bus_teardown_intr(), destroy_dev(), etc.)

-- 
John Baldwin [EMAIL PROTECTED]http://www.FreeBSD.org/~jhb/
Power Users Use the Power to Serve  =  http://www.FreeBSD.org
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: How to do proper locking

2005-08-04 Thread Hans Petter Selasky
On Thursday 04 August 2005 14:08, Max Laier wrote:
 On Thursday 04 August 2005 13:40, Hans Petter Selasky wrote:
  This is a copy and paste from the kernel sources:
 
  struct ucred *
  crhold(struct ucred *cr)
  {
  The problem is, what happens if the kernel switches thread right here,
  and then the other thread calls crfree() on this structure, that will
  free() memory pointed to by cr. Then the first line of code below
  will access freed memory, and then we are going for a segment fault or
  worse.
 
  mtx_lock(cr-cr_mtxp);
  cr-cr_ref++;
  mtx_unlock(cr-cr_mtxp);
  return (cr);
  }

 It seems that you are misunderstanding the concept of reference counting. 
 The idea is to have a reference as long as you are handing around the
 object.  In order to call crhold() you must already hold a reference to the
 credential. This will prevent the credential structure to vanish and allow
 you to pass the credential to another consumer that now can assume to hold
 a reference of it's own.

Maybe crhold() is not exactly what I am after. From what I can see, we are 
speaking about two different refcount systems:

- crhold()/crfree() is incrementing/decrementing the refcount to indicate the 
total number of references hold.

- I am only incrementing the refcount at object destruction, to make sure that 
the last refcount value cannot be used again, to get access to the object.


 If you can access your objects from a external list, you have to hold a
 global lock that protects:
  1) Sanity of the list
  2) Free operations to the member objects

Yes, that is what I am doing, but there is a problem. Here is another 
pseudo-code example on what I'm trying to get a solution for:

struct mtx global;

struct my_object {
  struct mtx *mtx;
  u_int8_t some_data[256];
  struct my_object *next;
} *m;

/* Here is the enforced locking order, which
 * makes most sense to me:
 *
 * 1. m-mtx
 * 2. global
 */

void()
thread_1()
{
  struct my_object *m;

  sleep(global);

  lock(global);
  /*
   * to access this object
   * we dequeue it from a
   * one-way linked list:
   */
  m = dequeue_object();
  mtx = m-mtx;
  unlock(global);

  wakeup(m);
  sleep(m);

  /* What makes this so special is that
   * the object pointed to by m is owned
   * by thread_2. When that thread
   * exits the object is gone.
   *
   * A big problem is that one cannot
   * hold any lock right here, to
   * block thread_2 from freeing the 
   * object, due to the enforced locking 
   * order. Switching locking order
   * does not change anything.
   */
  lock(mtx);

  /* When the CPU gets here a check
   * is neccesary to ensure that the
   * other thread has not freed the
   * object pointed to by m.
   */
  if(refcount_copy == some_atomic_read)
  {
/* object is still here */
  }

  unlock(mtx);

  return;
}

void
thread_2()
{
  struct my_object *m;

  m = malloc(sizeof(*m));

  if(m == NULL) return;

  m-mtx = mtx_alloc();

  lock(global);
  enqueue_object(m);
  unlock(global);

  wakeup(global);
  sleep(m);

  lock(global);
  remove_object_from_list_if_present(m);
  unlock(global);

  lock(mtx);

  /*
   * XXX increase some refcount atomically
   * XXX even if we are locked
   */
  unlock(mtx);

  free(m);

  wakeup(m);
  return;
}


 If you access the objects via the list/tree/whatsoever most of the time -
 refcounting isn't for you.


If you use a single lock, you don't need refcounting. But if you use two 
locks, like in this example, and you have more than one source of object 
destruction, refcounting is required.

Do you see that more than one thread can be about to destroy the object at the 
same time? 

--HPS
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: How to do proper locking

2005-08-04 Thread Hans Petter Selasky
On Thursday 04 August 2005 15:53, John Baldwin wrote:
 On Thursday 04 August 2005 07:40 am, Hans Petter Selasky wrote:
  On Wednesday 03 August 2005 19:21, John Baldwin wrote:
   On Tuesday 02 August 2005 06:23 pm, Hans Petter Selasky wrote:
Hi,
   
I am looking for a safe way to access structures that can be freed.
The solution I am looking for must not:
   
- hinder scaleability
- lead to use of a single lock
- lead to lock order reversal
 
  There is one more thing. When the structure is freed it should not block
  waiting for any reference counts.
 


 crhold() is always called when the caller knows that it has a reference to
 cr that can't go away.  Thus, in the case of p_ucred, one holds the
 associated PROC_LOCK() while doing crhold().  After the crhold() you can
 drop the proc lock, so that lock is only held for a very short period of
 time.  You then have your own reference to the cred structure that is valid
 until you call crfree().  In the case of curthread-td_ucred, the reference
 is valid until curthread releases it on a cred update at the start of a
 syscall, so your reference is valid without needing locks for the life of a
 syscall.  The key here is that you solve this problem at a higher level,
 not within the structure itself.

Yes, this works with mbufs, crhold() and alike, where one doesn't actually 
free the object until the refcount reaches zero. But I am speaking about 
destroying an object while the refcount is non-zero. Do you see the 
difference?

There are two ways to handle this:

1) blocking: wait until the refcount reaches zero.

2) nonblocking: increment some other refcount that the
   callback checks before accessing any data.


Do you agree that method 2 is going to:

- avoid deadlock
- avoid use of sx-locks, locks that allow calls to msleep(),
  to keep synchronization while destroying objects 
  with refcounts.


When calling functions like callout_stop(), it is likely that one is holding 
a lock to prevent other code from calling callout_start() on the same 
callback before callout_stop() has been called. Now, if callout_stop() 
sleeps, the lock that is held while calling this function, must allow calls 
msleep(). So this must be an sx-lock (see man sx). Now if one routine 
sleeps, then any callers of this routine must sleep too. So this affects the 
synchronization of the whole system.

Isn't nonblocking operation preferred over blocking operation?


   What actual problem are you trying to solve?
 
  Generic callbacks:
 
  - setting up timers. Make sure that callback is never called after that
  timer has been stopped.

 See callout_stop() and callout_drain().  callout_drain() won't return until
 the callout has both been stopped and has finished executing if it was
 already in progress.

The callback can be called after that callout_stop() has been called!

You can use _callout_stop_safe(), but the problem is that it will sleep, 
waiting for the other thread to finish. The solution I have described, 
makes this process non-blocking, which means that one can hold a lock while 
calling callout_stop() which must be an advantage.


  - setting up devices. Make sure that read/write/ioctl/poll callbacks are
  never called after that the device has been freed.

 This is managed with refcounts on the dev_t object by devfs.  Once you call
 destroy_dev() devfs manages the rest.

No, the callback functions read/write/ioctl/poll can be called after that 
destroy_dev() has been called.


  - setting up interrupts. Make sure that interrupt routine is never called
  after that it is been teared down.

 bus_teardown_intr() already does this.

I'm sure it is the same here. If the interrupt handler doesn't have its own 
lock then, I think the interrupt callback can be called after that 
bus_teardown_intr() has been called.


  And more. There are lots of situations in the kernel that run into the
  same scheme, without a proper solution.

 Are there any other places you can think of that don't handle this already?

I am thinking about all the device drivers that create devices in /dev/ that 
can be detache, and that really never checks anything before accessing the 
softc:
int
ulptread(struct cdev *dev, struct uio *uio, int flags)
{
struct ulpt_softc *sc;
int error;

USB_GET_SC(ulpt, ULPTUNIT(dev), sc);

XXX
XXX here can be an segmentation fault where sc == NULL
XXX


if (sc-sc_dying)
return (EIO);

sc-sc_refcnt++;
error = ulpt_do_read(sc, uio, flags);
if (--sc-sc_refcnt  0)
usb_detach_wakeup(USBDEV(sc-sc_dev));
return (error);
}

 The approach FreeBSD's kernel has taken is to solve this problem by
 duplicating a lot of checks all over the place for each data structure, but
 to solve it in the primitives themselves instead (hence callout_drain(),
 bus_teardown_intr(), destroy_dev(), etc.)

Yes, but why are the implementations based on blocking operation, hence this 

Re: How to do proper locking

2005-08-04 Thread John Baldwin
On Thursday 04 August 2005 12:50 pm, Hans Petter Selasky wrote:
 On Thursday 04 August 2005 15:53, John Baldwin wrote:
  On Thursday 04 August 2005 07:40 am, Hans Petter Selasky wrote:
   On Wednesday 03 August 2005 19:21, John Baldwin wrote:
On Tuesday 02 August 2005 06:23 pm, Hans Petter Selasky wrote:
 Hi,

 I am looking for a safe way to access structures that can be freed.
 The solution I am looking for must not:

 - hinder scaleability
 - lead to use of a single lock
 - lead to lock order reversal
  
   There is one more thing. When the structure is freed it should not
   block waiting for any reference counts.
 
  crhold() is always called when the caller knows that it has a reference
  to cr that can't go away.  Thus, in the case of p_ucred, one holds the
  associated PROC_LOCK() while doing crhold().  After the crhold() you can
  drop the proc lock, so that lock is only held for a very short period of
  time.  You then have your own reference to the cred structure that is
  valid until you call crfree().  In the case of curthread-td_ucred, the
  reference is valid until curthread releases it on a cred update at the
  start of a syscall, so your reference is valid without needing locks for
  the life of a syscall.  The key here is that you solve this problem at a
  higher level, not within the structure itself.

 Yes, this works with mbufs, crhold() and alike, where one doesn't actually
 free the object until the refcount reaches zero. But I am speaking about
 destroying an object while the refcount is non-zero. Do you see the
 difference?

 There are two ways to handle this:

 1) blocking: wait until the refcount reaches zero.

 2) nonblocking: increment some other refcount that the
callback checks before accessing any data.


 Do you agree that method 2 is going to:

 - avoid deadlock
 - avoid use of sx-locks, locks that allow calls to msleep(),
   to keep synchronization while destroying objects
   with refcounts.

Not always. :)

 When calling functions like callout_stop(), it is likely that one is
 holding a lock to prevent other code from calling callout_start() on the
 same callback before callout_stop() has been called. Now, if
 callout_stop() sleeps, the lock that is held while calling this function,
 must allow calls msleep(). So this must be an sx-lock (see man sx). Now
 if one routine sleeps, then any callers of this routine must sleep too. So
 this affects the synchronization of the whole system.

 Isn't nonblocking operation preferred over blocking operation?

You can call callout_stop() while holding the lock, then do a callout_drain() 
later when you are prepared to block.  This is what I'm doing with ethernet 
drivers right now that typically call callout_stop in their foo_stop() 
routine so detach looks like:

FOO_LOCK(sc);
foo_stop(sc);   // calls callout_stop()
FOO_UNLOCK(sc);
callout_drain(sc-foo_stat_ch);

 The callback can be called after that callout_stop() has been called!

 You can use _callout_stop_safe(), but the problem is that it will sleep,
 waiting for the other thread to finish. The solution I have described,
 makes this process non-blocking, which means that one can hold a lock while
 calling callout_stop() which must be an advantage.

See above.

   - setting up devices. Make sure that read/write/ioctl/poll callbacks
   are never called after that the device has been freed.
 
  This is managed with refcounts on the dev_t object by devfs.  Once you
  call destroy_dev() devfs manages the rest.

 No, the callback functions read/write/ioctl/poll can be called after that
 destroy_dev() has been called.

Nope.  Evert call to read/write/ioctl bumps a reference count on the 
underlying dev_t and destroy_dev() blocks until the reference count drops to 
zero.

   - setting up interrupts. Make sure that interrupt routine is never
   called after that it is been teared down.
 
  bus_teardown_intr() already does this.

 I'm sure it is the same here. If the interrupt handler doesn't have its own
 lock then, I think the interrupt callback can be called after that
 bus_teardown_intr() has been called.

Nope.  The interrupt code checks if the ithread is running and if so it flags 
the handler for removal and blocks to let the ithread remove the handler and 
then wake it up.

   And more. There are lots of situations in the kernel that run into the
   same scheme, without a proper solution.
 
  Are there any other places you can think of that don't handle this
  already?

 I am thinking about all the device drivers that create devices in /dev/
 that can be detache, and that really never checks anything before accessing
 the softc:

As above, since they use destroy_dev() they are already ok.

  The approach FreeBSD's kernel has taken is to solve this problem by
  duplicating a lot of checks all over the place for each data structure,
  but to solve it in the primitives themselves instead (hence
  

Re: How to do proper locking

2005-08-04 Thread David Malone
On Thu, Aug 04, 2005 at 06:50:12PM +0200, Hans Petter Selasky wrote:
 2) nonblocking: increment some other refcount that the
callback checks before accessing any data.

I think people usually call this something like a generation count.
This sort of scheme used to be used for vnodes in FreeBSD. If you
look through the archives for people talking about type-stable
storage, you'll probably find some details.

David.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: How to do proper locking

2005-08-04 Thread Hans Petter Selasky
On Thursday 04 August 2005 20:15, John Baldwin wrote:
 On Thursday 04 August 2005 12:50 pm, Hans Petter Selasky wrote:
  On Thursday 04 August 2005 15:53, John Baldwin wrote:
   On Thursday 04 August 2005 07:40 am, Hans Petter Selasky wrote:
On Wednesday 03 August 2005 19:21, John Baldwin wrote:
 On Tuesday 02 August 2005 06:23 pm, Hans Petter Selasky wrote:
  Hi,
 
  I am looking for a safe way to access structures that can be
  freed. The solution I am looking for must not:
 
  - hinder scaleability
  - lead to use of a single lock
  - lead to lock order reversal
   
There is one more thing. When the structure is freed it should not
block waiting for any reference counts.
  
   crhold() is always called when the caller knows that it has a reference
   to cr that can't go away.  Thus, in the case of p_ucred, one holds the
   associated PROC_LOCK() while doing crhold().  After the crhold() you
   can drop the proc lock, so that lock is only held for a very short
   period of time.  You then have your own reference to the cred structure
   that is valid until you call crfree().  In the case of
   curthread-td_ucred, the reference is valid until curthread releases it
   on a cred update at the start of a syscall, so your reference is valid
   without needing locks for the life of a syscall.  The key here is that
   you solve this problem at a higher level, not within the structure
   itself.
 
  Yes, this works with mbufs, crhold() and alike, where one doesn't
  actually free the object until the refcount reaches zero. But I am
  speaking about destroying an object while the refcount is non-zero. Do
  you see the difference?
 
  There are two ways to handle this:
 
  1) blocking: wait until the refcount reaches zero.
 
  2) nonblocking: increment some other refcount that the
 callback checks before accessing any data.
 
 
  Do you agree that method 2 is going to:
 
  - avoid deadlock
  - avoid use of sx-locks, locks that allow calls to msleep(),
to keep synchronization while destroying objects
with refcounts.

 Not always. :)

  When calling functions like callout_stop(), it is likely that one is
  holding a lock to prevent other code from calling callout_start() on
  the same callback before callout_stop() has been called. Now, if
  callout_stop() sleeps, the lock that is held while calling this
  function, must allow calls msleep(). So this must be an sx-lock (see man
  sx). Now if one routine sleeps, then any callers of this routine must
  sleep too. So this affects the synchronization of the whole system.
 
  Isn't nonblocking operation preferred over blocking operation?

 You can call callout_stop() while holding the lock, then do a
 callout_drain() later when you are prepared to block.  This is what I'm
 doing with ethernet drivers right now that typically call callout_stop in
 their foo_stop() routine so detach looks like:

  FOO_LOCK(sc);
  foo_stop(sc); // calls callout_stop()
  FOO_UNLOCK(sc);
  callout_drain(sc-foo_stat_ch);


This is only going to work if you are detaching. But consider the following:

  FOO_LOCK(sc);
  callout_stop();
  callout_start();
  FOO_UNLOCK(sc);

Your solution is only spinning halfway around. What I say is that you need 
some more parameters passed to callbacks, so that one can check if it has 
been cancelled before proceeding.


  No, the callback functions read/write/ioctl/poll can be called after that
  destroy_dev() has been called.

 Nope.  Every call to read/write/ioctl bumps a reference count on the
 underlying dev_t and destroy_dev() blocks until the reference count drops
 to zero.

Yes, I see that dev_refthread() and dev_relthread() are called from 
devfs_xxx(), but destroy_dev() will not wait for these refcounts to reach 
zero unless the d_purge field is initialized in struct cdevsw. And I 
cannot see that prep_cdevs() is setting any default value for this field. 
So by default destroy_dev() is non-blocking which is right.

I am a bit lazy today, so I did:

cat `find /usr/src/sys/dev/*` | grep d_purge

And got two hits. This feature is not used at all.


 
  What I want is that the kernel provides some routine that can do locking
  based on a structure like below. Also the kernel must provide some
  routines to allocate, free and read a refcount.
 
  struct callback_args {
void *sc;
struct mtx *p_mtx;
u_int32_t refcount_copy;
u_int32_t *p_refcount;
  };
 
  Then I want routines like callout_reset(), make_dev(),
  bus_setup_intr() and so on, to pass these four parameters to the
  callback function, either directly, or like a pointer to this structure.

 You are just going to move the blocking behavior into contention on your
 locks, you aren't going to actually remove it anywhere

Yes, that is correct, but from what I understand it is inherently more 
efficient to wait for a mutex of type struct mtx, than it is to use 
msleep/wakeup, which is the current way of doing it, according to 

Checking sysctl values from within the kernel.

2005-08-04 Thread Thordur I. Bjornsson
Hello list.

If I want to check a sysctl value from within the kernel (e.g. an KLD),
should I use the system calls described in sysctl(3) ?

If not, what is the propper way to do so ?

And if it is and I want to do error checking e.g:

if((sysctl(name, namelen, val, NULL, 0)) != 0) {
Error in call to sysctl(3) blah blah blah;
}

What would be the correct way to report,stop, c ?
This is propaply depentand on what I'm doing so...

If this is AA I'm sorry for the noize, I have not been able to find
anything on google/archives. (It's late ;)

-- 
Thordur I.  [EMAIL PROTECTED]
Humppa!
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]