int
main()
{
  pthread_t to, ti;
  pthread_mutexattr_t ma;

  assert(pthread_mutexattr_init(&ma) == 0);
  assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0);

  lockCount = 0;
  assert(pthread_mutex_init(&mutex[0], &ma) == 0);
  assert(pthread_mutex_init(&mutex[1], &ma) == 0);
  assert(pthread_mutex_init(&mutex[2], &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_create(&ti, NULL, inheritor, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 6);
  assert(pthread_mutex_lock(&mutex[0]) == EOWNERDEAD);
  assert(pthread_mutex_consistent(&mutex[0]) == 0);
  assert(pthread_mutex_unlock(&mutex[0]) == 0);
  assert(pthread_mutex_destroy(&mutex[0]) == 0);
  assert(pthread_mutex_lock(&mutex[1]) == EOWNERDEAD);
  assert(pthread_mutex_consistent(&mutex[1]) == 0);
  assert(pthread_mutex_unlock(&mutex[1]) == 0);
  assert(pthread_mutex_destroy(&mutex[1]) == 0);
  assert(pthread_mutex_lock(&mutex[2]) == EOWNERDEAD);
  assert(pthread_mutex_consistent(&mutex[2]) == 0);
  assert(pthread_mutex_unlock(&mutex[2]) == 0);
  assert(pthread_mutex_destroy(&mutex[2]) == 0);

  assert(pthread_mutexattr_destroy(&ma) == 0);

  return 0;
}
Exemple #2
0
void
mutex_init(void)
{
    /* 共享存储初始化 */
    if ((fd = open(shared_file, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0)
        err_sys("open error");
    if ((pmutex = mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == NULL)
        err_sys("mmap error");

    /* 互斥量初始化 */
    if ((pthread_mutexattr_init(&attr)) != 0)
        err_sys("pthread_mutexattr_init error");
    if ((pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) != 0) {
        pthread_mutexattr_destroy(&attr);
        err_sys("pthread_mutexattr_setpshared error");
    }
    /* 参考资料:http://blog.csdn.net/red_knight/article/details/50417898 */
    if ((pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) != 0) {
        pthread_mutexattr_destroy(&attr);
        err_sys("pthread_mutexattr_setpshared error");
    }
    if ((pthread_mutex_init(pmutex, &attr)) != 0) {
        pthread_mutexattr_destroy(&attr);
        err_sys("pthread_mutex_init error");
    }
    pthread_mutexattr_destroy(&attr);
}
static void f()
{
	pthread_t td;
	int r;
	pthread_mutexattr_t mtx_a;
	pthread_mutex_t mtx;
	struct timespec ts;

	T(r, pthread_barrier_init(&barrier2, 0, 2));
	T(r, pthread_mutexattr_init(&mtx_a));
	T(r, pthread_mutexattr_setrobust(&mtx_a, PTHREAD_MUTEX_ROBUST));
	if (pshared)
		T(r, pthread_mutexattr_setpshared(&mtx_a, PTHREAD_PROCESS_SHARED));
	T(r, pthread_mutex_init(&mtx, &mtx_a));
	T(r, pthread_create(&td, 0, start_lock, &mtx));
	T(r, pthread_detach(td));
	pthread_barrier_wait(&barrier2);
	pthread_barrier_destroy(&barrier2);

	// enough time to ensure that the detached thread is dead
	clock_gettime(CLOCK_REALTIME, &ts);
	ts.tv_nsec += 100*1000*1000;
	if (ts.tv_nsec >= 1000*1000*1000) {
		ts.tv_sec++;
		ts.tv_nsec -= 1000*1000*1000;
	}

	TX(r, pthread_mutex_timedlock(&mtx, &ts), EOWNERDEAD);
}
Exemple #4
0
/**
 * Mutex
 */
LPDM_MUTEX mutexNew(const char *name)
{
    LPDM_MUTEX m = NULL;
#ifdef WIN32
    m = CreateMutexA(NULL, FALSE, name);
    if(m == NULL){
        DWORD dwError = GetLastError();
        if(dwError == ERROR_ACCESS_DENIED)
            m = OpenMutexA(SYNCHRONIZE, FALSE, name);
    }
#else
	pthread_mutexattr_t mutexattr;

	pthread_mutexattr_init(&mutexattr);
    m = (LPDM_MUTEX)malloc(sizeof(DM_MUTEX));
    m->context = NULL;
    if(name){
        int mutexexist = 0;
        mutexexist = shm_exist(name);
        m->context = mmapOpen(name, sizeof(pthread_mutex_t));
        m->mutex = (pthread_mutex_t*)m->context->data;
        if(mutexexist)
            return m;
        pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
        pthread_mutexattr_setrobust(&mutexattr, PTHREAD_MUTEX_ROBUST);
    }
    else
        m->mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));

	pthread_mutex_init(m->mutex, &mutexattr);
	pthread_mutexattr_destroy(&mutexattr);
#endif
    return m;
}
Exemple #5
0
int tdb_mutex_init(struct tdb_context *tdb)
{
	struct tdb_mutexes *m;
	pthread_mutexattr_t ma;
	int i, ret;

	ret = tdb_mutex_mmap(tdb);
	if (ret == -1) {
		return -1;
	}
	m = tdb->mutexes;

	ret = pthread_mutexattr_init(&ma);
	if (ret != 0) {
		goto fail_munmap;
	}
	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
	if (ret != 0) {
		goto fail;
	}
	ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	if (ret != 0) {
		goto fail;
	}
	ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	if (ret != 0) {
		goto fail;
	}

	for (i=0; i<tdb->hash_size+1; i++) {
		pthread_mutex_t *chain = &m->hashchains[i];

		ret = pthread_mutex_init(chain, &ma);
		if (ret != 0) {
			goto fail;
		}
	}

	m->allrecord_lock = F_UNLCK;

	ret = pthread_mutex_init(&m->allrecord_mutex, &ma);
	if (ret != 0) {
		goto fail;
	}
	ret = 0;
fail:
	pthread_mutexattr_destroy(&ma);
fail_munmap:

	if (ret == 0) {
		return 0;
	}

	tdb_mutex_munmap(tdb);

	errno = ret;
	return -1;
}
Exemple #6
0
int
mutex_init (pthread_mutex_t *mutex, int flags, int robust)
{
  pthread_mutexattr_t mattr;

  pthread_mutexattr_init (&mattr);
  pthread_mutexattr_settype (&mattr, flags);
  pthread_mutexattr_setrobust (&mattr, robust);

  return pthread_mutex_init (mutex, &mattr);
}
Exemple #7
0
/*!
 * \brief Create the share memory mutex.
 *
 * \param key   Shared memory key.
 * \param addr  Starting address of attached shared memory.
 * \param size  Shared memory size.
 */
static void shm_mutex_create(key_t key, void *addr, size_t size)
{
  pthread_mutex_t      *pmutex = (pthread_mutex_t *)addr;
  pthread_mutexattr_t   mutexAttr;

  pthread_mutexattr_init(&mutexAttr);

  //
  // Set the attribute to share between applications.
  //
  if(pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED) < 0)
  {
    LOGSYSERROR("pthread_mutexattr_setpshared()");
  }

#ifndef ARCH_overo
  //
  // Set mutex robust attribute. If the owning thread or application terminates,
  // the next thread/application acquiring the mutex is notified by the 
  // return value EOWNERDEAD.
  //
  else if( pthread_mutexattr_setrobust(&mutexAttr, PTHREAD_MUTEX_ROBUST) < 0 )
  {
    LOGSYSERROR("pthread_mutexattr_setrobust()");
  }

  //
  // Allow recursive locks by the owning thread or application.
  //
  else if( pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) < 0 )
  {
    LOGSYSERROR("pthread_mutexattr_settype()");
  }
#endif // ARCH_overo

  //
  // Initialize the pthread mutex with the give attributes
  //
  else if( pthread_mutex_init(pmutex, &mutexAttr) < 0 )
  {
    LOGSYSERROR("pthread_mutex_init()");
  }

  //
  // Success.
  //
  else
  {
    LOGDIAG4("Shared memory mutex created.");
  }

  pthread_mutexattr_destroy(&mutexAttr);
}
Exemple #8
0
void init_logging()
{
	pthread_mutexattr_t mutexattr;
	loglevel = LOG_INFO;
	is_a_tty = isatty(STDOUT_FILENO);

	pthread_mutexattr_init(&mutexattr);
#ifndef __APPLE__
	pthread_mutexattr_setrobust(&mutexattr, PTHREAD_MUTEX_ROBUST);
#endif
	pthread_mutex_init(&mutex, &mutexattr);
}
Exemple #9
0
CThreadMutex::CThreadMutex(void)
{
#ifdef _WINDOWS
	m_Crit = new CRITICAL_SECTION;
	InitializeCriticalSection( (LPCRITICAL_SECTION)m_Crit );
	//No Error Code here
#else
	pthread_mutexattr_t ma;
	CHECK_UNIX_ERROR(pthread_mutexattr_init(&ma));
	CHECK_UNIX_ERROR(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE));
	CHECK_UNIX_ERROR(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_STALLED));
	CHECK_UNIX_ERROR(pthread_mutex_init(&m_mutex, &ma));
	CHECK_UNIX_ERROR(pthread_mutexattr_destroy(&ma));
#endif
}
static int
do_test (void)
{
  pthread_mutexattr_t a;
  if (pthread_mutexattr_init (&a) != 0)
    {
      puts ("mutexattr_init failed");
      return 1;
    }

  if (pthread_mutexattr_setrobust (&a, PTHREAD_MUTEX_ROBUST) != 0)
    {
      puts ("mutexattr_setrobust failed");
      return 1;
    }

#ifdef ENABLE_PI
  if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
    {
      puts ("pthread_mutexattr_setprotocol failed");
      return 1;
    }
#endif

  int e;
  e = pthread_mutex_init (&m, &a);
  if (e != 0)
    {
#ifdef ENABLE_PI
      if (e == ENOTSUP)
	{
	  puts ("PI robust mutexes not supported");
	  return 0;
	}
#endif
      puts ("mutex_init failed");
      return 1;
    }

  if (pthread_mutexattr_destroy (&a) != 0)
    {
      puts ("mutexattr_destroy failed");
      return 1;
    }

  if (pthread_barrier_init (&b, NULL, 2) != 0)
    {
      puts ("barrier_init failed");
      return 1;
    }

#define N 5
  pthread_t th[N];
  for (long int n = 0; n < N; ++n)
    {
      if (pthread_create (&th[n], NULL, tf, (void *) n) != 0)
	{
	  printf ("pthread_create loop %ld failed\n", n + 1);
	  return 1;
	}

      e = pthread_barrier_wait (&b);
      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
	{
	  printf ("parent: barrier_wait failed in round %ld\n", n + 1);
	  return 1;
	}
    }

  if (pthread_mutex_lock (&m) != 0)
    {
      puts ("parent: mutex_lock failed");
      return 1;
    }

  if (pthread_mutex_unlock (&m) != 0)
    {
      puts ("parent: mutex_unlock failed");
      return 1;
    }

  if (pthread_cond_broadcast (&c) != 0)
    {
      puts ("cond_broadcast failed");
      return 1;
    }

  for (int n = 0; n < N; ++n)
    {
      void *res;
      if (pthread_join (th[n], &res) != 0)
	{
	  printf ("join round %d failed\n", n + 1);
	  return 1;
	}
      if (res != PTHREAD_CANCELED)
	{
	  printf ("thread %d not canceled\n", n + 1);
	  return 1;
	}
    }

  e = pthread_mutex_lock (&m);
  if (e == 0)
    {
      puts ("parent: 2nd mutex_lock succeeded");
      return 1;
    }
  if (e != EOWNERDEAD)
    {
      puts ("parent: mutex_lock did not return EOWNERDEAD");
      return 1;
    }

  if (pthread_mutex_unlock (&m) != 0)
    {
      puts ("parent: 2nd mutex_unlock failed");
      return 1;
    }

  if (pthread_mutex_destroy (&m) != 0)
    {
      puts ("mutex_destroy failed");
      return 1;
    }

  return 0;
}
Exemple #11
0
int
main()
{
  pthread_t to, ti;
  pthread_mutexattr_t ma;
  int order[3];

  assert(pthread_mutexattr_init(&ma) == 0);
  assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0);

  order[0]=0;
  order[1]=1;
  order[2]=2;
  lockCount = 0;
  assert(pthread_mutex_init(&mutex[0], &ma) == 0);
  assert(pthread_mutex_init(&mutex[1], &ma) == 0);
  assert(pthread_mutex_init(&mutex[2], &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 6);
  assert(pthread_mutex_lock(&mutex[0]) == 0);
  assert(pthread_mutex_unlock(&mutex[0]) == 0);
  assert(pthread_mutex_destroy(&mutex[0]) == 0);
  assert(pthread_mutex_lock(&mutex[1]) == 0);
  assert(pthread_mutex_unlock(&mutex[1]) == 0);
  assert(pthread_mutex_destroy(&mutex[1]) == 0);
  assert(pthread_mutex_lock(&mutex[2]) == 0);
  assert(pthread_mutex_unlock(&mutex[2]) == 0);
  assert(pthread_mutex_destroy(&mutex[2]) == 0);

  order[0]=1;
  order[1]=0;
  order[2]=2;
  lockCount = 0;
  assert(pthread_mutex_init(&mutex[0], &ma) == 0);
  assert(pthread_mutex_init(&mutex[1], &ma) == 0);
  assert(pthread_mutex_init(&mutex[2], &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 6);
  assert(pthread_mutex_lock(&mutex[0]) == 0);
  assert(pthread_mutex_unlock(&mutex[0]) == 0);
  assert(pthread_mutex_destroy(&mutex[0]) == 0);
  assert(pthread_mutex_lock(&mutex[1]) == 0);
  assert(pthread_mutex_unlock(&mutex[1]) == 0);
  assert(pthread_mutex_destroy(&mutex[1]) == 0);
  assert(pthread_mutex_lock(&mutex[2]) == 0);
  assert(pthread_mutex_unlock(&mutex[2]) == 0);
  assert(pthread_mutex_destroy(&mutex[2]) == 0);

  order[0]=0;
  order[1]=2;
  order[2]=1;
  lockCount = 0;
  assert(pthread_mutex_init(&mutex[0], &ma) == 0);
  assert(pthread_mutex_init(&mutex[1], &ma) == 0);
  assert(pthread_mutex_init(&mutex[2], &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 6);
  assert(pthread_mutex_lock(&mutex[0]) == 0);
  assert(pthread_mutex_unlock(&mutex[0]) == 0);
  assert(pthread_mutex_destroy(&mutex[0]) == 0);
  assert(pthread_mutex_lock(&mutex[1]) == 0);
  assert(pthread_mutex_unlock(&mutex[1]) == 0);
  assert(pthread_mutex_destroy(&mutex[1]) == 0);
  assert(pthread_mutex_lock(&mutex[2]) == 0);
  assert(pthread_mutex_unlock(&mutex[2]) == 0);
  assert(pthread_mutex_destroy(&mutex[2]) == 0);

  order[0]=2;
  order[1]=1;
  order[2]=0;
  lockCount = 0;
  assert(pthread_mutex_init(&mutex[0], &ma) == 0);
  assert(pthread_mutex_init(&mutex[1], &ma) == 0);
  assert(pthread_mutex_init(&mutex[2], &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 6);
  assert(pthread_mutex_lock(&mutex[0]) == 0);
  assert(pthread_mutex_unlock(&mutex[0]) == 0);
  assert(pthread_mutex_destroy(&mutex[0]) == 0);
  assert(pthread_mutex_lock(&mutex[1]) == 0);
  assert(pthread_mutex_unlock(&mutex[1]) == 0);
  assert(pthread_mutex_destroy(&mutex[1]) == 0);
  assert(pthread_mutex_lock(&mutex[2]) == 0);
  assert(pthread_mutex_unlock(&mutex[2]) == 0);
  assert(pthread_mutex_destroy(&mutex[2]) == 0);

  assert(pthread_mutexattr_destroy(&ma) == 0);

  return 0;
}
Exemple #12
0
int
main (int argc, char *argv[])
{
  pthread_t t;

  assert(pthread_mutexattr_init(&ma) == 0);

  printf( "=============================================================================\n");
  printf( "\nTrylock on a locked mutex.\n");
  printf( "%ld iterations.\n\n", ITERATIONS);
  printf( "%-45s %15s %15s\n",
	    "Test",
	    "Total(msec)",
	    "average(usec)");
  printf( "-----------------------------------------------------------------------------\n");

  /*
   * Time the loop overhead so we can subtract it from the actual test times.
   */

  TESTSTART
  TESTSTOP

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  overHeadMilliSecs = durationMilliSecs;


  old_mutex_use = OLD_WIN32CS;
  assert(old_mutex_init(&ox, NULL) == 0);
  assert(old_mutex_lock(&ox) == 0);
  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
  assert(pthread_join(t, NULL) == 0);
  assert(old_mutex_unlock(&ox) == 0);
  assert(old_mutex_destroy(&ox) == 0);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Critical Section (WNT)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);

  old_mutex_use = OLD_WIN32MUTEX;
  assert(old_mutex_init(&ox, NULL) == 0);
  assert(old_mutex_lock(&ox) == 0);
  assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0);
  assert(pthread_join(t, NULL) == 0);
  assert(old_mutex_unlock(&ox) == 0);
  assert(old_mutex_destroy(&ox) == 0);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Win32 Mutex (W9x)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);

  printf( ".............................................................................\n");

  /*
   * Now we can start the actual tests
   */
#ifdef  __PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( ".............................................................................\n");

  pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);

#ifdef  __PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( "=============================================================================\n");

  /*
   * End of tests.
   */

  pthread_mutexattr_destroy(&ma);

  return 0;
}
Exemple #13
0
enum ach_status
ach_create( const char *channel_name,
            size_t frame_cnt, size_t frame_size,
            ach_create_attr_t *attr) {
    ach_header_t *shm;
    int fd;
    size_t len;
    /* fixme: truncate */
    /* open shm */
    {
        len = sizeof( ach_header_t) +
            frame_cnt*sizeof( ach_index_t ) +
            frame_cnt*frame_size +
            3*sizeof(uint64_t);

        if( attr && attr->map_anon ) {
            /* anonymous (heap) */
            shm = (ach_header_t *) malloc( len );
            fd = -1;
        }else {
            int oflag = O_EXCL | O_CREAT;
            /* shm */
            if( ! channel_name_ok( channel_name ) )
                return ACH_INVALID_NAME;
            if( attr ) {
                if( attr->truncate ) oflag &= ~O_EXCL;
            }
            if( (fd = fd_for_channel_name( channel_name, oflag )) < 0 ) {
                return check_errno();;
            }

            { /* make file proper size */
                /* FreeBSD needs ftruncate before mmap, Linux can do either order */
                int r;
                int i = 0;
                do {
                    r = ftruncate( fd, (off_t) len );
                }while(-1 == r && EINTR == errno && i++ < ACH_INTR_RETRY);
                if( -1 == r ) {
                    DEBUG_PERROR( "ftruncate");
                    return ACH_FAILED_SYSCALL;
                }
            }

            /* mmap */
            if( (shm = (ach_header_t *)mmap( NULL, len, PROT_READ|PROT_WRITE,
                                             MAP_SHARED, fd, 0) )
                == MAP_FAILED ) {
                DEBUG_PERROR("mmap");
                DEBUGF("mmap failed %s, len: %"PRIuPTR", fd: %d\n", strerror(errno), len, fd);
                return ACH_FAILED_SYSCALL;
            }

        }

        memset( shm, 0, len );
        shm->len = len;
    }

    { /* initialize synchronization */
        { /* initialize condition variables */
            int r;
            pthread_condattr_t cond_attr;
            if( (r = pthread_condattr_init(&cond_attr)) ) {
                DEBUG_PERROR("pthread_condattr_init");
                return ACH_FAILED_SYSCALL;
            }
            /* Process Shared */
            if( ! (attr && attr->map_anon) ) {
                /* Set shared if not anonymous mapping
                   Default will be private. */
                if( (r = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED)) ) {
                    DEBUG_PERROR("pthread_condattr_setpshared");
                    return ACH_FAILED_SYSCALL;
                }
            }
            /* Clock */
            if( attr && attr->set_clock ) {
                if( (r = pthread_condattr_setclock(&cond_attr, attr->clock)) ) {
                    DEBUG_PERROR("pthread_condattr_setclock");
                    return ACH_FAILED_SYSCALL;
                }
            } else {
                if( (r = pthread_condattr_setclock(&cond_attr, ACH_DEFAULT_CLOCK)) ) {
                    DEBUG_PERROR("pthread_condattr_setclock");
                    return ACH_FAILED_SYSCALL;
                }
            }

            if( (r = pthread_cond_init(&shm->sync.cond, &cond_attr)) ) {
                DEBUG_PERROR("pthread_cond_init");
                return ACH_FAILED_SYSCALL;
            }

            if( (r = pthread_condattr_destroy(&cond_attr)) ) {
                DEBUG_PERROR("pthread_condattr_destroy");
                return ACH_FAILED_SYSCALL;
            }
        }
        { /* initialize mutex */
            int r;
            pthread_mutexattr_t mutex_attr;
            if( (r = pthread_mutexattr_init(&mutex_attr)) ) {
                DEBUG_PERROR("pthread_mutexattr_init");
                return ACH_FAILED_SYSCALL;
            }
            if( (r = pthread_mutexattr_setpshared(&mutex_attr,
                                                  PTHREAD_PROCESS_SHARED)) ) {
                DEBUG_PERROR("pthread_mutexattr_setpshared");
                return ACH_FAILED_SYSCALL;
            }
#ifdef HAVE_MUTEX_PRIORITY_INHERIT
            /* Priority Inheritance Mutex */
            if( (r = pthread_mutexattr_setprotocol(&mutex_attr,
                                                   PTHREAD_PRIO_INHERIT)) ) {
                DEBUG_PERROR("pthread_mutexattr_setprotocol");
                return ACH_FAILED_SYSCALL;
            }
#endif
#ifdef HAVE_MUTEX_ROBUST
            /* Robust Mutex */
            if( (r = pthread_mutexattr_setrobust(&mutex_attr,
                                                 PTHREAD_MUTEX_ROBUST)) ) {
                DEBUG_PERROR("pthread_mutexattr_setrobust");
                return ACH_FAILED_SYSCALL;
            }
#endif
#ifdef HAVE_MUTEX_ERROR_CHECK
            /* Error Checking Mutex */
            if( (r = pthread_mutexattr_settype(&mutex_attr,
                                               PTHREAD_MUTEX_ERRORCHECK)) ) {
                DEBUG_PERROR("pthread_mutexattr_settype");
                return ACH_FAILED_SYSCALL;
            }
#endif
            if( (r = pthread_mutex_init(&shm->sync.mutex, &mutex_attr)) ) {
                DEBUG_PERROR("pthread_mutexattr_init");
                return ACH_FAILED_SYSCALL;
            }

            if( (r = pthread_mutexattr_destroy(&mutex_attr)) ) {
                DEBUG_PERROR("pthread_mutexattr_destroy");
                return ACH_FAILED_SYSCALL;
            }
        }
    }
    /* initialize name */
    strncpy( shm->name, channel_name, ACH_CHAN_NAME_MAX );
    /* initialize counts */
    shm->index_cnt = frame_cnt;
    shm->index_head = 0;
    shm->index_free = frame_cnt;
    shm->data_head = 0;
    shm->data_free = frame_cnt * frame_size;
    shm->data_size = frame_cnt * frame_size;
    assert( sizeof( ach_header_t ) +
            shm->index_free * sizeof( ach_index_t ) +
            shm->data_free + 3*sizeof(uint64_t) ==  len );

    *ACH_SHM_GUARD_HEADER(shm) = ACH_SHM_GUARD_HEADER_NUM;
    *ACH_SHM_GUARD_INDEX(shm) = ACH_SHM_GUARD_INDEX_NUM;
    *ACH_SHM_GUARD_DATA(shm) = ACH_SHM_GUARD_DATA_NUM;
    shm->magic = ACH_SHM_MAGIC_NUM;

    if( attr && attr->map_anon ) {
        attr->shm = shm;
    } else {
        int r;
        /* remove mapping */
        r = munmap(shm, len);
        if( 0 != r ){
            DEBUG_PERROR("munmap");
            return ACH_FAILED_SYSCALL;
        }
        /* close file */
        int i = 0;
        do {
            IFDEBUG( i ? DEBUGF("Retrying close()\n"):0 );
            r = close(fd);
        }while( -1 == r && EINTR == errno && i++ < ACH_INTR_RETRY );
        if( -1 == r ){
            DEBUG_PERROR("close");
            return ACH_FAILED_SYSCALL;
        }
    }
    return ACH_OK;
}
int
main (int argc, char *argv[])
{
  int i = 0;
  CRITICAL_SECTION cs;
  old_mutex_t ox;
  pthread_mutexattr_init(&ma);

  printf( "=============================================================================\n");
  printf( "\nLock plus unlock on an unlocked mutex.\n%ld iterations\n\n",
          ITERATIONS);
  printf( "%-45s %15s %15s\n",
	    "Test",
	    "Total(msec)",
	    "average(usec)");
  printf( "-----------------------------------------------------------------------------\n");

  /*
   * Time the loop overhead so we can subtract it from the actual test times.
   */
  TESTSTART
  assert(1 == one);
  assert(2 == two);
  TESTSTOP

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  overHeadMilliSecs = durationMilliSecs;


  TESTSTART
  assert((dummy_call(&i), 1) == one);
  assert((dummy_call(&i), 2) == two);
  TESTSTOP

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "Dummy call x 2",
          durationMilliSecs,
          (float) (durationMilliSecs * 1E3 / ITERATIONS));


  TESTSTART
  assert((interlocked_inc_with_conditionals(&i), 1) == one);
  assert((interlocked_dec_with_conditionals(&i), 2) == two);
  TESTSTOP

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "Dummy call -> Interlocked with cond x 2",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);


  TESTSTART
  assert((InterlockedIncrement((LPLONG)&i), 1) == (LONG)one);
  assert((InterlockedDecrement((LPLONG)&i), 2) == (LONG)two);
  TESTSTOP

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "InterlockedOp x 2",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);


  InitializeCriticalSection(&cs);

  TESTSTART
  assert((EnterCriticalSection(&cs), 1) == one);
  assert((LeaveCriticalSection(&cs), 2) == two);
  TESTSTOP

  DeleteCriticalSection(&cs);

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "Simple Critical Section",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);


  old_mutex_use = OLD_WIN32CS;
  assert(old_mutex_init(&ox, NULL) == 0);

  TESTSTART
  assert(old_mutex_lock(&ox) == zero);
  assert(old_mutex_unlock(&ox) == zero);
  TESTSTOP

  assert(old_mutex_destroy(&ox) == 0);

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Critical Section (WNT)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);


  old_mutex_use = OLD_WIN32MUTEX;
  assert(old_mutex_init(&ox, NULL) == 0);

  TESTSTART
  assert(old_mutex_lock(&ox) == zero);
  assert(old_mutex_unlock(&ox) == zero);
  TESTSTOP

  assert(old_mutex_destroy(&ox) == 0);

  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;

  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Win32 Mutex (W9x)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS);

  printf( ".............................................................................\n");

  /*
   * Now we can start the actual tests
   */
#ifdef PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( ".............................................................................\n");

  pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);

#ifdef PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( "=============================================================================\n");

  /*
   * End of tests.
   */

  pthread_mutexattr_destroy(&ma);

  one = i; /* Dummy assignment to avoid 'variable unused' warning */
  return 0;
}
Exemple #15
0
_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
{
	void *ptr = NULL;
	pthread_mutex_t *m = NULL;
	pthread_mutexattr_t ma;
	int ret = 1;
	int pipe_down[2] = { -1, -1 };
	int pipe_up[2] = { -1, -1 };
	ssize_t nread;
	char c = 0;
	bool ok;
	static bool initialized;
	pid_t saved_child_pid = -1;
	bool cleanup_ma = false;

	if (initialized) {
		return tdb_mutex_locking_cached;
	}

	initialized = true;

	ok = tdb_mutex_locking_supported();
	if (!ok) {
		return false;
	}

	tdb_mutex_locking_cached = false;

	ptr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE,
		   MAP_SHARED|MAP_ANON, -1 /* fd */, 0);
	if (ptr == MAP_FAILED) {
		return false;
	}

	ret = pipe(pipe_down);
	if (ret != 0) {
		goto cleanup;
	}
	ret = pipe(pipe_up);
	if (ret != 0) {
		goto cleanup;
	}

	ret = pthread_mutexattr_init(&ma);
	if (ret != 0) {
		goto cleanup;
	}
	cleanup_ma = true;
	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
	if (ret != 0) {
		goto cleanup;
	}
	ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	if (ret != 0) {
		goto cleanup;
	}
	ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	if (ret != 0) {
		goto cleanup;
	}
	ret = pthread_mutex_init(ptr, &ma);
	if (ret != 0) {
		goto cleanup;
	}
	m = (pthread_mutex_t *)ptr;

	if (tdb_robust_mutex_setup_sigchild(tdb_robust_mutex_handler,
			&tdb_robust_mutext_old_handler) == false) {
		goto cleanup;
	}

	tdb_robust_mutex_pid = fork();
	saved_child_pid = tdb_robust_mutex_pid;
	if (tdb_robust_mutex_pid == 0) {
		size_t nwritten;
		close(pipe_down[1]);
		close(pipe_up[0]);
		ret = pthread_mutex_lock(m);
		nwritten = write(pipe_up[1], &ret, sizeof(ret));
		if (nwritten != sizeof(ret)) {
			_exit(1);
		}
		if (ret != 0) {
			_exit(1);
		}
		nread = read(pipe_down[0], &c, 1);
		if (nread != 1) {
			_exit(1);
		}
		/* leave locked */
		_exit(0);
	}
	if (tdb_robust_mutex_pid == -1) {
		goto cleanup;
	}
	close(pipe_down[0]);
	pipe_down[0] = -1;
	close(pipe_up[1]);
	pipe_up[1] = -1;

	nread = read(pipe_up[0], &ret, sizeof(ret));
	if (nread != sizeof(ret)) {
		goto cleanup;
	}

	ret = pthread_mutex_trylock(m);
	if (ret != EBUSY) {
		if (ret == 0) {
			pthread_mutex_unlock(m);
		}
		goto cleanup;
	}

	if (write(pipe_down[1], &c, 1) != 1) {
		goto cleanup;
	}

	nread = read(pipe_up[0], &c, 1);
	if (nread != 0) {
		goto cleanup;
	}

	tdb_robust_mutex_wait_for_child(&saved_child_pid);

	ret = pthread_mutex_trylock(m);
	if (ret != EOWNERDEAD) {
		if (ret == 0) {
			pthread_mutex_unlock(m);
		}
		goto cleanup;
	}

	ret = pthread_mutex_consistent(m);
	if (ret != 0) {
		goto cleanup;
	}

	ret = pthread_mutex_trylock(m);
	if (ret != EDEADLK && ret != EBUSY) {
		pthread_mutex_unlock(m);
		goto cleanup;
	}

	ret = pthread_mutex_unlock(m);
	if (ret != 0) {
		goto cleanup;
	}

	tdb_mutex_locking_cached = true;

cleanup:
	/*
	 * Note that we don't reset the signal handler we just reset
	 * tdb_robust_mutex_pid to -1. This is ok as this code path is only
	 * called once per process.
	 *
	 * Leaving our signal handler avoids races with other threads potentialy
	 * setting up their SIGCHLD handlers.
	 *
	 * The worst thing that can happen is that the other newer signal
	 * handler will get the SIGCHLD signal for our child and/or reap the
	 * child with a wait() function. tdb_robust_mutex_wait_for_child()
	 * handles the case where waitpid returns ECHILD.
	 */
	tdb_robust_mutex_wait_for_child(&saved_child_pid);

	if (m != NULL) {
		pthread_mutex_destroy(m);
	}
	if (cleanup_ma) {
		pthread_mutexattr_destroy(&ma);
	}
	if (pipe_down[0] != -1) {
		close(pipe_down[0]);
	}
	if (pipe_down[1] != -1) {
		close(pipe_down[1]);
	}
	if (pipe_up[0] != -1) {
		close(pipe_up[0]);
	}
	if (pipe_up[1] != -1) {
		close(pipe_up[1]);
	}
	if (ptr != NULL) {
		munmap(ptr, sizeof(pthread_mutex_t));
	}

	return tdb_mutex_locking_cached;
}
Exemple #16
0
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!! 
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {

	pthread_mutexattr_t attr;

	struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);

#ifdef EOWNERDEAD
retry:
#endif
	if (pthread_mutexattr_init(&attr)) {
		uwsgi_log("unable to allocate mutexattr structure\n");
		exit(1);
	}

	if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
		uwsgi_log("unable to share mutex\n");
		exit(1);
	}

#ifdef EOWNERDEAD
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#define pthread_mutexattr_setrobust pthread_mutexattr_setrobust_np
#define pthread_mutex_consistent pthread_mutex_consistent_np
#endif
	if (uwsgi_pthread_robust_mutexes_enabled) {
		int ret;
		if ((ret = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) != 0) {
			switch (ret) {
			case ENOTSUP:
				// PTHREAD_PRIO_INHERIT will only prevent
				// priority inversion when SCHED_FIFO or
				// SCHED_RR is used, so this is non-fatal and
				// also currently unsupported on musl.
				break;
			default:
				uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
				exit(1);
			}
		}
		if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) {
			uwsgi_log("unable to make the mutex 'robust'\n");
			exit(1);
		}
	}
#endif

	if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
#ifdef EOWNERDEAD
		if (uwsgi_pthread_robust_mutexes_enabled) {
			uwsgi_log("!!! it looks like your kernel does not support pthread robust mutexes !!!\n");
			uwsgi_log("!!! falling back to standard pthread mutexes !!!\n");
			uwsgi_pthread_robust_mutexes_enabled = 0;
			pthread_mutexattr_destroy(&attr);
			goto retry;
		}
#endif
		uwsgi_log("unable to initialize mutex\n");
		exit(1);
	}

	pthread_mutexattr_destroy(&attr);

#ifdef EOWNERDEAD
	if (!uwsgi_pthread_robust_mutexes_enabled) {
		uli->can_deadlock = 1;
	}
#else
	uli->can_deadlock = 1;
#endif

	return uli;
}
Exemple #17
0
_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void)
{
	void *ptr;
	pthread_mutex_t *m;
	pthread_mutexattr_t ma;
	int ret = 1;
	int pipe_down[2] = { -1, -1 };
	int pipe_up[2] = { -1, -1 };
	ssize_t nread;
	char c = 0;
	bool ok;
	int status;
	static bool initialized;

	if (initialized) {
		return tdb_mutex_locking_cached;
	}

	initialized = true;

	ok = tdb_mutex_locking_supported();
	if (!ok) {
		return false;
	}

	tdb_mutex_locking_cached = false;

	ptr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE,
		   MAP_SHARED|MAP_ANON, -1 /* fd */, 0);
	if (ptr == MAP_FAILED) {
		return false;
	}
	m = (pthread_mutex_t *)ptr;

	ret = pipe(pipe_down);
	if (ret != 0) {
		goto cleanup_mmap;
	}
	ret = pipe(pipe_up);
	if (ret != 0) {
		goto cleanup_pipe;
	}

	ret = pthread_mutexattr_init(&ma);
	if (ret != 0) {
		goto cleanup_pipe;
	}
	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutex_init(m, &ma);
	if (ret != 0) {
		goto cleanup_ma;
	}

	tdb_robust_mutext_old_handler = signal(SIGCHLD,
					       tdb_robust_mutex_handler);

	tdb_robust_mutex_pid = fork();
	if (tdb_robust_mutex_pid == 0) {
		size_t nwritten;
		close(pipe_down[1]);
		close(pipe_up[0]);
		ret = pthread_mutex_lock(m);
		nwritten = write(pipe_up[1], &ret, sizeof(ret));
		if (nwritten != sizeof(ret)) {
			exit(1);
		}
		if (ret != 0) {
			exit(1);
		}
		nread = read(pipe_down[0], &c, 1);
		if (nread != 1) {
			exit(1);
		}
		/* leave locked */
		exit(0);
	}
	if (tdb_robust_mutex_pid == -1) {
		goto cleanup_sig_child;
	}
	close(pipe_down[0]);
	pipe_down[0] = -1;
	close(pipe_up[1]);
	pipe_up[1] = -1;

	nread = read(pipe_up[0], &ret, sizeof(ret));
	if (nread != sizeof(ret)) {
		goto cleanup_child;
	}

	ret = pthread_mutex_trylock(m);
	if (ret != EBUSY) {
		if (ret == 0) {
			pthread_mutex_unlock(m);
		}
		goto cleanup_child;
	}

	if (write(pipe_down[1], &c, 1) != 1) {
		goto cleanup_child;
	}

	nread = read(pipe_up[0], &c, 1);
	if (nread != 0) {
		goto cleanup_child;
	}

	while (tdb_robust_mutex_pid > 0) {
		pid_t pid;

		errno = 0;
		pid = waitpid(tdb_robust_mutex_pid, &status, 0);
		if (pid == tdb_robust_mutex_pid) {
			tdb_robust_mutex_pid = -1;
			break;
		}
		if (pid == -1 && errno != EINTR) {
			goto cleanup_child;
		}
	}
	signal(SIGCHLD, tdb_robust_mutext_old_handler);

	ret = pthread_mutex_trylock(m);
	if (ret != EOWNERDEAD) {
		if (ret == 0) {
			pthread_mutex_unlock(m);
		}
		goto cleanup_m;
	}

	ret = pthread_mutex_consistent(m);
	if (ret != 0) {
		goto cleanup_m;
	}

	ret = pthread_mutex_trylock(m);
	if (ret != EDEADLK) {
		pthread_mutex_unlock(m);
		goto cleanup_m;
	}

	ret = pthread_mutex_unlock(m);
	if (ret != 0) {
		goto cleanup_m;
	}

	tdb_mutex_locking_cached = true;
	goto cleanup_m;

cleanup_child:
	while (tdb_robust_mutex_pid > 0) {
		pid_t pid;

		kill(tdb_robust_mutex_pid, SIGKILL);

		errno = 0;
		pid = waitpid(tdb_robust_mutex_pid, &status, 0);
		if (pid == tdb_robust_mutex_pid) {
			tdb_robust_mutex_pid = -1;
			break;
		}
		if (pid == -1 && errno != EINTR) {
			break;
		}
	}
cleanup_sig_child:
	signal(SIGCHLD, tdb_robust_mutext_old_handler);
cleanup_m:
	pthread_mutex_destroy(m);
cleanup_ma:
	pthread_mutexattr_destroy(&ma);
cleanup_pipe:
	if (pipe_down[0] != -1) {
		close(pipe_down[0]);
	}
	if (pipe_down[1] != -1) {
		close(pipe_down[1]);
	}
	if (pipe_up[0] != -1) {
		close(pipe_up[0]);
	}
	if (pipe_up[1] != -1) {
		close(pipe_up[1]);
	}
cleanup_mmap:
	munmap(ptr, sizeof(pthread_mutex_t));

	return tdb_mutex_locking_cached;
}
Exemple #18
0
int
main()
{
  pthread_t to, ti;
  pthread_mutexattr_t ma;

  assert(pthread_mutexattr_init(&ma) == 0);
  assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0);

  /* Default (NORMAL) type */ 
  lockCount = 0;
  assert(pthread_mutex_init(&mutex, &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, NULL) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 2);
  assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE);
  assert(pthread_mutex_destroy(&mutex) == 0);

  /* NORMAL type */ 
  lockCount = 0;
  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_NORMAL) == 0);
  assert(pthread_mutex_init(&mutex, &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, NULL) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 2);
  assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE);
  assert(pthread_mutex_destroy(&mutex) == 0);

  /* ERRORCHECK type */ 
  lockCount = 0;
  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0);
  assert(pthread_mutex_init(&mutex, &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, NULL) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 2);
  assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE);
  assert(pthread_mutex_destroy(&mutex) == 0);

  /* RECURSIVE type */ 
  lockCount = 0;
  assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE) == 0);
  assert(pthread_mutex_init(&mutex, &ma) == 0);
  assert(pthread_create(&to, NULL, owner, NULL) == 0);
  Sleep(100);
  assert(pthread_create(&ti, NULL, inheritor, NULL) == 0);
  assert(pthread_join(to, NULL) == 0);
  assert(pthread_join(ti, NULL) == 0);
  assert(lockCount == 2);
  assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE);
  assert(pthread_mutex_destroy(&mutex) == 0);

  assert(pthread_mutexattr_destroy(&ma) == 0);

  return 0;
}
Exemple #19
0
/*----------------------------------------------------------------------------*/
static udps_err_t udps_lock_init(void)
{
    int                 smfd;
    pthread_mutexattr_t mattr;
    int                 rc;

    /* If the shared memory object already exists, unlink it. */
    shm_unlink(UDPS_SM_OBJ_NAME);

    /* Create a new share memory object.
     * O_RDWR  = Open for reading and writing.
     * O_CREAT = Create the shared memory object if it does not exist.
     * O_EXCL  = If the given name already exists, return an error.
     * S_IRUSR = User has read permission.
     * S_IWUSR = User has write permission. */
    LOG_SRV(UDPS_LOG_DEBUG, ("Creating shared memory object..."));
    smfd = shm_open(UDPS_SM_OBJ_NAME, (O_RDWR|O_CREAT|O_EXCL|O_TRUNC),
                    (S_IRUSR|S_IWUSR));
    if(smfd < 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not create share memory object: "
                                 "%s (%d)", strerror(errno), errno));
        return UDPS_ERR_SMEM_OBJ_CREATE;
    }
    rc = ftruncate(smfd, sizeof(pthread_mutex_t));
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not truncate share memory object: "
                                 "%s (%d)", strerror(errno), errno));
        return UDPS_ERR_SMEM_OBJ_TRUNC;
    }

    /* Create a new mapping in the virtual address space.
     * NULL       = The kernel chooses the address at which to create the
     *              mapping.
     * PROT_READ  = Pages may be read.
     * PROT_WRITE = Pages may be written.
     * MAP_SHARED = Updates to the mapping are visible to other processes
     *              that map this file. */
    LOG_SRV(UDPS_LOG_DEBUG, ("Creating shared memory mapping..."));
    srv.mptr = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t),
                                      (PROT_READ|PROT_WRITE), MAP_SHARED,
                                      smfd, 0);
    if(srv.mptr == MAP_FAILED) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not create share memory mapping: "
                                 "%s (%d)", strerror(errno), errno));
        close(smfd);
        return UDPS_ERR_SMEM_MAP_CREATE;
    }

    /* Close shared memory object. */
    LOG_SRV(UDPS_LOG_DEBUG, ("Closing shared memory object..."));
    if(close(smfd) != 0) {
        LOG_SRV(UDPS_LOG_WARNING, ("Could not close shared memory object: "
                                   "%s (%d)", strerror(errno), errno));
    }

    /* Create processes controller mutex.
     * PTHREAD_PROCESS_SHARED = permit a mutex to be operated upon by any thread
     *                          that has access to the memory where the mutex is
     *                          allocated, even if the mutex is allocated in
     *                          memory that is shared by multiple processes.
     * PTHREAD_MUTEX_ROBUST   = If the process containing the owning thread of a
     *                          robust mutex terminates while holding the mutex
     *                          lock, the next thread that acquires the mutex
     *                          shall be notified about the termination by the
     *                          return value [EOWNERDEAD] from the locking
     *                          function. */
    LOG_SRV(UDPS_LOG_DEBUG, ("Creating processes controler mutex..."));
    rc = pthread_mutexattr_init(&mattr);
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not create pthread mutex attribute: "
                                 "%d", rc));
        return UDPS_ERR_SMEM_ATTR_CREATE;
    }
    rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not set pthread mutex attribute as "
                                 "shared: %d", rc));
        pthread_mutexattr_destroy(&mattr);
        return UDPS_ERR_SMEM_ATTR_SET;
    }
    rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not set pthread mutex attribute as "
                                 "robust: %d", rc));
        pthread_mutexattr_destroy(&mattr);
        return UDPS_ERR_SMEM_ATTR_SET;
    }
    rc = pthread_mutex_init(srv.mptr, &mattr);
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_EMERG, ("Could not initialize pthread mutex: %d",
                                 rc));
        pthread_mutexattr_destroy(&mattr);
        return UDPS_ERR_SMEM_MUTEX_INIT;
    }

    /* Close unneeded pthread mutex attribute. */
    LOG_SRV(UDPS_LOG_DEBUG, ("Destroying unneeded pthread mutex attribute..."));
    rc = pthread_mutexattr_destroy(&mattr);
    if(rc != 0) {
        LOG_SRV(UDPS_LOG_WARNING, ("Could not close pthread mutex attribute: "
                                   "%d", rc));
    }

    return UDPS_OK;
}
Exemple #20
0
static bool tdb_mutex_locking_supported(void)
{
	pthread_mutexattr_t ma;
	pthread_mutex_t m;
	int ret;
	static bool initialized;

	if (initialized) {
		return tdb_mutex_locking_cached;
	}

	initialized = true;

	ret = pthread_mutexattr_init(&ma);
	if (ret != 0) {
		return false;
	}
	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutex_init(&m, &ma);
	if (ret != 0) {
		goto cleanup_ma;
	}
	ret = pthread_mutex_lock(&m);
	if (ret != 0) {
		goto cleanup_m;
	}
	/*
	 * This makes sure we have real mutexes
	 * from a threading library instead of just
	 * stubs from libc.
	 */
	ret = pthread_mutex_lock(&m);
	if (ret != EDEADLK) {
		goto cleanup_lock;
	}
	ret = pthread_mutex_unlock(&m);
	if (ret != 0) {
		goto cleanup_m;
	}

	tdb_mutex_locking_cached = true;
	goto cleanup_m;

cleanup_lock:
	pthread_mutex_unlock(&m);
cleanup_m:
	pthread_mutex_destroy(&m);
cleanup_ma:
	pthread_mutexattr_destroy(&ma);
	return tdb_mutex_locking_cached;
}
Exemple #21
0
int
test_benchtest2(void)
#endif
{
  assert(pthread_mutexattr_init(&ma) == 0);

  printf( "=============================================================================\n");
  printf( "\nLock plus unlock on a locked mutex.\n");
  printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS);

  printf( "%-45s %15s %15s\n",
	    "Test",
	    "Total(msec)",
	    "average(usec)");
  printf( "-----------------------------------------------------------------------------\n");

  /*
   * Time the loop overhead so we can subtract it from the actual test times.
   */

  running = 1;
  assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0);
  TESTSTART;
  sched_yield();
  sched_yield();
  TESTSTOP;
  running = 0;
  assert(pthread_join(worker, NULL) == 0);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  overHeadMilliSecs = durationMilliSecs;


  InitializeCriticalSection(&cs1);
  InitializeCriticalSection(&cs2);
  EnterCriticalSection(&cs1);
  EnterCriticalSection(&cs2);
  running = 1;
  assert(pthread_create(&worker, NULL, CSThread, NULL) == 0);
  TESTSTART;
  LeaveCriticalSection(&cs1);
  sched_yield();
  LeaveCriticalSection(&cs2);
  EnterCriticalSection(&cs1);
  EnterCriticalSection(&cs2);
  TESTSTOP;
  running = 0;
  LeaveCriticalSection(&cs2);
  LeaveCriticalSection(&cs1);
  assert(pthread_join(worker, NULL) == 0);
  DeleteCriticalSection(&cs2);
  DeleteCriticalSection(&cs1);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  printf( "%-45s %15ld %15.3f\n",
	    "Simple Critical Section",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS / 4 );


  old_mutex_use = OLD_WIN32CS;
  assert(old_mutex_init(&ox1, NULL) == 0);
  assert(old_mutex_init(&ox2, NULL) == 0);
  assert(old_mutex_lock(&ox1) == 0);
  assert(old_mutex_lock(&ox2) == 0);
  running = 1;
  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
  TESTSTART;
  (void) old_mutex_unlock(&ox1);
  sched_yield();
  (void) old_mutex_unlock(&ox2);
  (void) old_mutex_lock(&ox1);
  (void) old_mutex_lock(&ox2);
  TESTSTOP;
  running = 0;
  assert(old_mutex_unlock(&ox1) == 0);
  assert(old_mutex_unlock(&ox2) == 0);
  assert(pthread_join(worker, NULL) == 0);
  assert(old_mutex_destroy(&ox2) == 0);
  assert(old_mutex_destroy(&ox1) == 0);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Critical Section (WNT)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);


  old_mutex_use = OLD_WIN32MUTEX;
  assert(old_mutex_init(&ox1, NULL) == 0);
  assert(old_mutex_init(&ox2, NULL) == 0);
  assert(old_mutex_lock(&ox1) == 0);
  assert(old_mutex_lock(&ox2) == 0);
  running = 1;
  assert(pthread_create(&worker, NULL, oldThread, NULL) == 0);
  TESTSTART;
  (void) old_mutex_unlock(&ox1);
  sched_yield();
  (void) old_mutex_unlock(&ox2);
  (void) old_mutex_lock(&ox1);
  (void) old_mutex_lock(&ox2);
  TESTSTOP;
  running = 0;
  assert(old_mutex_unlock(&ox1) == 0);
  assert(old_mutex_unlock(&ox2) == 0);
  assert(pthread_join(worker, NULL) == 0);
  assert(old_mutex_destroy(&ox2) == 0);
  assert(old_mutex_destroy(&ox1) == 0);
  durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs;
  printf( "%-45s %15ld %15.3f\n",
	    "Old PT Mutex using a Win32 Mutex (W9x)",
          durationMilliSecs,
          (float) durationMilliSecs * 1E3 / ITERATIONS / 4);

  printf( ".............................................................................\n");

  /*
   * Now we can start the actual tests
   */
#ifdef PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( ".............................................................................\n");

  pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);

#ifdef PTW32_MUTEX_TYPES
  runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT);

  runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL);

  runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK);

  runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE);
#else
  runTest("Non-blocking lock", 0);
#endif

  printf( "=============================================================================\n");
  /*
   * End of tests.
   */

  pthread_mutexattr_destroy(&ma);

  return 0;
}
Exemple #22
0
int main(int argc, const char **argv)
{
	pthread_mutexattr_t ma;
	pthread_mutex_t *mutex;
	int fd, ret, i;
	pid_t pid;
	void *addr;
	int num_children;
	int priority = PRIO_NORMAL;

	if (argc < 3 || argc > 4) {
		fprintf(stderr, "Usage: %s <file> <n> [0|1|2]\n", argv[0]);
		fprintf(stderr, "       %s <file> debug\n", argv[0]);
		exit(1);
	}

	if (argc == 4) {
		priority = atoi(argv[3]);
	}

	if (priority == PRIO_REALTIME) {
		set_realtime();
	} else if (priority == PRIO_NICE_20) {
		high_priority();
	}

	fd = open(argv[1], O_CREAT|O_RDWR, 0600);
	if (fd == -1) {
		fprintf(stderr, "open failed\n");
		exit(1);
	}

	ret = lseek(fd, 0, SEEK_SET);
	if (ret != 0) {
		fprintf(stderr, "lseek failed\n");
		exit(1);
	}

	ret = ftruncate(fd, sizeof(pthread_mutex_t));
	if (ret != 0) {
		fprintf(stderr, "ftruncate failed\n");
		exit(1);
	}

	addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE,
		    MAP_SHARED|MAP_FILE, fd, 0);
	if (addr == NULL) {
		fprintf(stderr, "mmap failed\n");
		exit(1);
	}

	mutex = (pthread_mutex_t *)addr;

	if (strcmp(argv[2], "debug") == 0) {
		ret = pthread_mutex_trylock(mutex);
		if (ret == EOWNERDEAD) {
			ret = pthread_mutex_consistent(mutex);
			if (ret == 0) {
				pthread_mutex_unlock(mutex);
			}
		} else if (ret == EBUSY) {
			printf("pid=%u\n", mutex->__data.__owner);
		} else if (ret == 0) {
			pthread_mutex_unlock(mutex);
		}
		exit(0);
	}

	ret = pthread_mutexattr_init(&ma);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutexattr_init failed\n");
		exit(1);
	}

	ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutexattr_settype failed\n");
		exit(1);
	}

	ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutexattr_setpshared failed\n");
		exit(1);
	}

	ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutexattr_setrobust failed\n");
		exit(1);
	}

	ret = pthread_mutex_init(mutex, &ma);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutex_init failed\n");
		exit(1);
	}

	ret = pthread_mutex_lock(mutex);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutex_lock failed\n");
		exit(1);
	}

	setpgid(0, 0);

	fprintf(stderr, "Creating children\n");
	num_children = atoi(argv[2]);

	for (i=0; i<num_children; i++) {
		pid = fork();
		if (pid < 0) {
			fprintf(stderr, "fork() failed\n");
			exit(1);
		}
		if (pid == 0) {
			close(fd);
			run_child(argv[1]);
			exit(1);
		}
	}

	fprintf(stderr, "Waiting for children\n");

	ret = pthread_mutex_unlock(mutex);
	if (ret != 0) {
		fprintf(stderr, "pthread_mutex_unlock failed\n");
		exit(1);
	}

	for (i=0; i<num_children; i++) {
		int status;

		pid = waitpid(-1, &status, 0);
		if (pid <= 0) {
			fprintf(stderr, "waitpid() failed\n");
		}
	}

	close(fd);
	unlink(argv[1]);
	exit(0);
}
Exemple #23
0
am_shm_t *am_shm_create(const char *name, size_t usize) {
    struct mem_pool *pool = NULL;
    size_t size;
    char opened = AM_FALSE;
    void *area = NULL;
    am_shm_t *ret = NULL;
#ifdef _WIN32
    char dll_path[AM_URI_SIZE];
    DWORD error = 0;
    HMODULE hm = NULL;
    void *caller = _ReturnAddress();
#else
    int fdflags;
    int error = 0;
#endif

    ret = calloc(1, sizeof(am_shm_t));
    if (ret == NULL) return NULL;

#ifdef _WIN32
    if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) caller, &hm) &&
            GetModuleFileNameA(hm, dll_path, sizeof(dll_path) - 1) > 0) {
        PathRemoveFileSpecA(dll_path);
        strcat(dll_path, FILE_PATH_SEP);
        snprintf(ret->name[0], sizeof(ret->name[0]),
                AM_GLOBAL_PREFIX"%s_l", name); /* mutex/semaphore */
        snprintf(ret->name[1], sizeof(ret->name[1]),
                AM_GLOBAL_PREFIX"%s_s", name); /* shared memory name */
        snprintf(ret->name[2], sizeof(ret->name[2]),
                "%s.."FILE_PATH_SEP"log"FILE_PATH_SEP"%s_f", dll_path, name); /* shared memory file name */
        snprintf(ret->name[3], sizeof(ret->name[3]),
                AM_GLOBAL_PREFIX"%s_sz", name); /* shared memory name for global_size */
    } else {
        ret->error = AM_NOT_FOUND;
        return ret;
    }
#else
    snprintf(ret->name[0], sizeof(ret->name[0]),
            "/%s_l", name); /* mutex/semaphore */
    snprintf(ret->name[1], sizeof(ret->name[1]),
#ifdef __sun
            "/%s_s"
#else
            "%s_s"
#endif
            , name); /* shared memory name */
#endif

    size = page_size(usize + SIZEOF_mem_pool); /* need at least the size of the mem_pool header */

#ifdef _WIN32
    ret->h[0] = CreateMutexA(NULL, TRUE, ret->name[0]);
    error = GetLastError();
    if (ret->h[0] != NULL && error == ERROR_ALREADY_EXISTS) {
        do {
            error = WaitForSingleObject(ret->h[0], INFINITE);
        } while (error == WAIT_ABANDONED);
    } else {
        if (error == ERROR_ACCESS_DENIED) {
            ret->h[0] = OpenMutexA(SYNCHRONIZE, FALSE, ret->name[0]);
        }
        if (ret->h[0] == NULL) {
            ret->error = error;
            return ret;
        }
    }

    ret->h[1] = CreateFileA(ret->name[2], GENERIC_WRITE | GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL, CREATE_NEW, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL);
    error = GetLastError();
    if (ret->h[1] == INVALID_HANDLE_VALUE && error == ERROR_FILE_EXISTS) {
        ret->h[1] = CreateFileA(ret->name[2], GENERIC_WRITE | GENERIC_READ,
                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL);
        error = GetLastError();
        if (ret->h[1] != INVALID_HANDLE_VALUE) {
            opened = AM_TRUE;
            size = GetFileSize(ret->h[1], NULL);
        }
    }

    if (ret->h[1] == INVALID_HANDLE_VALUE || error != 0) {
        CloseHandle(ret->h[0]);
        ret->error = error;
        am_shm_unlock(ret);
        return ret;
    }

    if (!opened) {
        ret->h[2] = CreateFileMappingA(ret->h[1], NULL, PAGE_READWRITE, 0, (DWORD) size, ret->name[1]);
        error = GetLastError();
    } else {
        ret->h[2] = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, ret->name[1]);
        error = GetLastError();
        if (ret->h[2] == NULL && error == ERROR_FILE_NOT_FOUND) {
            ret->h[2] = CreateFileMappingA(ret->h[1], NULL, PAGE_READWRITE, 0, (DWORD) size, ret->name[1]);
            error = GetLastError();
        }
    }

    if (ret->h[2] == NULL || error != 0) {
        CloseHandle(ret->h[0]);
        CloseHandle(ret->h[1]);
        ret->error = error;
        am_shm_unlock(ret);
        return ret;
    }

    area = MapViewOfFile(ret->h[2], FILE_MAP_ALL_ACCESS, 0, 0, 0);
    error = GetLastError();
    if (area == NULL || (error != 0 && error != ERROR_ALREADY_EXISTS)) {
        CloseHandle(ret->h[0]);
        CloseHandle(ret->h[1]);
        CloseHandle(ret->h[2]);
        ret->error = error;
        am_shm_unlock(ret);
        return ret;
    }

    ret->h[3] = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD) sizeof(size_t), ret->name[3]);
    if (ret->h[3] == NULL) {
        ret->error = GetLastError();
        CloseHandle(ret->h[0]);
        CloseHandle(ret->h[1]);
        CloseHandle(ret->h[2]);
        am_shm_unlock(ret);
        return ret;
    }
    ret->global_size = MapViewOfFile(ret->h[3], FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (ret->global_size == NULL) {
        ret->error = GetLastError();
        CloseHandle(ret->h[0]);
        CloseHandle(ret->h[1]);
        CloseHandle(ret->h[2]);
        CloseHandle(ret->h[3]);
        am_shm_unlock(ret);
        return ret;
    }
    *(ret->global_size) = ret->local_size = size;

#else

    ret->lock = mmap(NULL, sizeof(pthread_mutex_t),
            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
    if (ret->lock == MAP_FAILED) {
        ret->error = errno;
        return ret;
    } else {
        pthread_mutexattr_t attr;
        pthread_mutex_t *lock = (pthread_mutex_t *) ret->lock;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#if defined(__sun)
#if defined(__SunOS_5_10) 
#if defined(_POSIX_THREAD_PRIO_INHERIT)
        pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
        pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
#endif
#else
        pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
#endif
#endif
#if defined(LINUX)
        pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
#endif
        pthread_mutex_init(lock, &attr);
        pthread_mutexattr_destroy(&attr);
    }

    ret->global_size = mmap(NULL, sizeof(size_t),
            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
    if (ret->global_size == MAP_FAILED) {
        ret->error = errno;
        return ret;
    }

    *(ret->global_size) = ret->local_size = size;

    am_shm_lock(ret);

    ret->fd = shm_open(ret->name[1], O_CREAT | O_EXCL | O_RDWR, 0666);
    error = errno;
    if (ret->fd == -1 && error != EEXIST) {
        munmap(ret->lock, sizeof(pthread_mutex_t));
        ret->error = error;
        am_shm_unlock(ret);
        return ret;
    }
    if (ret->fd == -1) {
        ret->fd = shm_open(ret->name[1], O_RDWR, 0666);
        error = errno;
        if (ret->fd == -1) {
            munmap(ret->lock, sizeof(pthread_mutex_t));
            ret->error = error;
            am_shm_unlock(ret);
            return ret;
        }
        /* reset FD_CLOEXEC */
        fdflags = fcntl(ret->fd, F_GETFD);
        fdflags &= ~FD_CLOEXEC;
        fcntl(ret->fd, F_SETFD, fdflags);
        /* try with just a header */
        area = mmap(NULL, SIZEOF_mem_pool, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0);
        if (area == MAP_FAILED) {
            ret->error = errno;
            am_shm_unlock(ret);
            return ret;
        }
        size = ((struct mem_pool *) area)->size;
        if (munmap(area, SIZEOF_mem_pool) == -1) {
            ret->error = errno;
            am_shm_unlock(ret);
            return ret;
        }
        area = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0);
        if (area == MAP_FAILED) {
            ret->error = errno;
            am_shm_unlock(ret);
            return ret;
        }
        opened = AM_TRUE;
    } else {
        /* reset FD_CLOEXEC */
        fdflags = fcntl(ret->fd, F_GETFD);
        fdflags &= ~FD_CLOEXEC;
        fcntl(ret->fd, F_SETFD, fdflags);
        if (ftruncate(ret->fd, size) == -1) {
            ret->error = errno;
            am_shm_unlock(ret);
            return ret;
        }
        area = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0);
        if (area == MAP_FAILED) {
            ret->error = errno;
            am_shm_unlock(ret);
            return ret;
        }
    }

#endif

    ret->init = !opened;

    pool = (struct mem_pool *) area;
    if (ret->init) {
        struct mem_chunk *e = (struct mem_chunk *) ((char *) pool + SIZEOF_mem_pool);
        pool->size = size;
        pool->user_offset = 0;
        pool->open = 1;
        pool->resize = 0;

        /* add all available (free) space as one chunk in a freelist */
        e->used = 0;
        e->usize = 0;
        e->size = pool->size - SIZEOF_mem_pool;
        e->lh.next = e->lh.prev = 0;
        /* update head prev/next pointers */
        pool->lh.next = pool->lh.prev = AM_GET_OFFSET(pool, e);
    } else {
        if (pool->user_offset > 0) {
            ret->user = AM_GET_POINTER(pool, pool->user_offset);
        }
        pool->open++;
    }

    ret->pool = pool;
    ret->error = 0;
    am_shm_unlock(ret);
    return ret;
}