mempool.c revision 58badbb3393efc20f87a0ca462c5ba463eb3e8ba
165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm/* libunwind - a platform-independent unwind library
265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm   Copyright (C) 2002-2003 Hewlett-Packard Co
365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmThis file is part of libunwind.
665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidma copy of this software and associated documentation files (the
965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm"Software"), to deal in the Software without restriction, including
1065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
1165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
1265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
1365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmthe following conditions:
1465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
1565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmThe above copyright notice and this permission notice shall be
1665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmincluded in all copies or substantial portions of the Software.
1765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
1865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
2565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
2665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include <assert.h>
2765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include <stdlib.h>
2865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include <string.h>
2965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include <unistd.h>
3065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
3165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include <sys/mman.h>
3265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
3365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include "libunwind.h"
3465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#include "mempool.h"
3565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
3665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#define MAX_ALIGN	(sizeof (long double))
3765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#define SOS_MEMORY_SIZE	16384
3865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
3965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic char sos_memory[SOS_MEMORY_SIZE];
4065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic char *sos_memp;
4165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic size_t pg_size;
4265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
4365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void *
4465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmsos_alloc (size_t size)
4565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
4665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  char *mem;
4765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
4865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#ifdef HAVE_CMPXCHG
4965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  char *old_mem;
5065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
5165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  size = (size + MAX_ALIGN - 1) & -MAX_ALIGN;
5265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  if (!sos_memp)
5365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    cmpxchg_ptr (&sos_memp, 0, sos_memory);
5465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  do
5565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    {
5665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      old_mem = sos_memp;
5765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
5865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      mem = (char *) (((unsigned long) old_mem + MAX_ALIGN - 1) & -MAX_ALIGN);
5965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      mem += size;
6065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      if (mem >= sos_memory + sizeof (sos_memory))
6165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	abort ();
6265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    }
6365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  while (!cmpxchg_ptr (&sos_memp, old_mem, mem));
6465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#else
6565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  static pthread_mutex_t sos_lock = PTHREAD_MUTEX_INITIALIZER;
6665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigset_t saved_sigmask;
6765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
6865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  size = (size + MAX_ALIGN - 1) & -MAX_ALIGN;
6965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
7065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
7165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_lock(&sos_lock);
7265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  {
7365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    if (!sos_memp)
7465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      sos_memp = sos_memory;
7565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
7665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    mem = (char *) (((unsigned long) sos_memp + MAX_ALIGN - 1) & -MAX_ALIGN);
7765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    mem += size;
7865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    if (mem >= sos_memory + sizeof (sos_memory))
7965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      abort ();
8065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    sos_memp = mem;
8165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  }
8265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_unlock(&sos_lock);
8365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
8465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#endif
8565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  return mem;
8665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
8765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
8865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void *
8965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmalloc_memory (size_t size)
9065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
9165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  /* Hopefully, mmap() goes straight through to a system call stub...  */
9265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  void *mem = mmap (0, size, PROT_READ | PROT_WRITE,
9365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm		    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
9465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  if (mem == MAP_FAILED)
9565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    return NULL;
9665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
9765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  return mem;
9865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
9965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
10065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm/* Must be called while holding the mempool lock. */
10165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
10265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void
10365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmfree_object (struct mempool *pool, void *object)
10465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
10565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  struct object *obj = object;
10665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
10765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  obj->next = pool->free_list;
10865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  pool->free_list = obj;
10965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  ++pool->num_free;
11065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
11165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
11265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void
11365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmadd_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size)
11465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
11565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  char *obj;
11665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
11758badbb3393efc20f87a0ca462c5ba463eb3e8bamostang.com!davidm  for (obj = mem; obj <= mem + size - obj_size; obj += obj_size)
11865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    free_object (pool, obj);
11965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
12065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
12165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void
12265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmexpand (struct mempool *pool)
12365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
12465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  size_t size;
12565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  char *mem;
12665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
12765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  size = pool->chunk_size;
12865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mem = alloc_memory (size);
12965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  if (!mem)
13065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    {
13165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      size = (pool->obj_size + pg_size - 1) & -pg_size;
13265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      mem = alloc_memory (size);
13365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      if (!mem)
13465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	{
13565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	  /* last chance: try to allocate one object from the SOS memory */
13665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	  size = pool->obj_size;
13765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	  mem = sos_alloc (size);
13865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	}
13965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    }
14065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  add_memory (pool, mem, size, pool->obj_size);
14165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
14265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
14365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void
14465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_init (struct mempool *pool, size_t obj_size, size_t reserve)
14565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
14665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  if (pg_size == 0)
14765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    pg_size = getpagesize ();
14865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
14965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  memset (pool, 0, sizeof (*pool));
15065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
15165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_init (&pool->lock);
15265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
15365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  /* round object-size up to integer multiple of MAX_ALIGN */
15465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  obj_size = (obj_size + MAX_ALIGN - 1) & -MAX_ALIGN;
15565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
15665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  if (!reserve)
15765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    {
15865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      reserve = pg_size / obj_size / 2;
15965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      if (!reserve)
16065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm	reserve = 16;
16165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    }
16265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
16365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  pool->obj_size = obj_size;
16465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  pool->reserve = reserve;
16565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  pool->chunk_size = (2*reserve*obj_size + pg_size - 1) & -pg_size;
16665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
16765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  expand (pool);
16865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
16965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
17065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void *
17165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_alloc (struct mempool *pool)
17265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
17365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigset_t saved_sigmask;
17465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  struct object *obj;
17565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
17665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
17765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_lock(&pool->lock);
17865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  {
17965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    if (pool->num_free <= pool->reserve)
18065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm      expand (pool);
18165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
18265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    assert (pool->num_free > 0);
18365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
18465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    --pool->num_free;
18565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    obj = pool->free_list;
18665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    pool->free_list = obj->next;
18765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  }
18865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_unlock(&pool->lock);
18965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
19065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  return obj;
19165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
19265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
19365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void
19465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_free (struct mempool *pool, void *object)
19565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{
19665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigset_t saved_sigmask;
19765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm
19865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &unwi_full_sigmask, &saved_sigmask);
19965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_lock(&pool->lock);
20065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  {
20165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm    free_object (pool, object);
20265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  }
20365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  mutex_unlock(&pool->lock);
20465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm  sigprocmask (SIG_SETMASK, &saved_sigmask, NULL);
20565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm}
206