コード例 #1
0
ファイル: pth_sync.c プロジェクト: YaroslavLitvinov/zrt
int pth_rwlock_acquire(pth_rwlock_t *rwlock, int op, int tryonly, pth_event_t ev_extra)
{
    /* consistency checks */
    if (rwlock == NULL)
        return pth_error(FALSE, EINVAL);
    if (!(rwlock->rw_state & PTH_RWLOCK_INITIALIZED))
        return pth_error(FALSE, EDEADLK);

    /* acquire lock */
    if (op == PTH_RWLOCK_RW) {
        /* read-write lock is simple */
        if (!pth_mutex_acquire(&(rwlock->rw_mutex_rw), tryonly, ev_extra))
            return FALSE;
        rwlock->rw_mode = PTH_RWLOCK_RW;
    }
    else {
        /* read-only lock is more complicated to get right */
        if (!pth_mutex_acquire(&(rwlock->rw_mutex_rd), tryonly, ev_extra))
            return FALSE;
        rwlock->rw_readers++;
        if (rwlock->rw_readers == 1) {
            if (!pth_mutex_acquire(&(rwlock->rw_mutex_rw), tryonly, ev_extra)) {
                rwlock->rw_readers--;
                pth_shield { pth_mutex_release(&(rwlock->rw_mutex_rd)); }
                return FALSE;
            }
        }
        rwlock->rw_mode = PTH_RWLOCK_RD;
        pth_mutex_release(&(rwlock->rw_mutex_rd));
    }
コード例 #2
0
ファイル: b5-pth.c プロジェクト: alepharchives/cpc
int
main()
{
    pth_t thread;
    int rc;
    int i, j, s;

    arg = -1;
    res = 0;
    pth_init();
    thread = pth_spawn(PTH_ATTR_DEFAULT, thread_routine, NULL);
    
    for(i = 0; i < 100; i++) {
        s = 0;
        for(j = 0; j < 10000; j++) {
            pth_mutex_acquire(&mutex, FALSE, NULL);
            res = -1;
            arg = j;
            pth_mutex_release(&mutex);
            pth_cond_notify(&c1, FALSE);
            pth_mutex_acquire(&mutex, FALSE, NULL);
            if(res < 0)
                pth_cond_await(&c2, &mutex, NULL);
            s += res;
            arg = -1;
            pth_mutex_release(&mutex);
        }
    }
    printf("%d\n", s);
    return 0;
}
コード例 #3
0
ファイル: call-pinentry.c プロジェクト: HoraceWeebler/gnupg
/* Returns True is the pinentry is currently active. If WAITSECONDS is
   greater than zero the function will wait for this many seconds
   before returning.  */
int
pinentry_active_p (ctrl_t ctrl, int waitseconds)
{
  (void)ctrl;

  if (waitseconds > 0)
    {
      pth_event_t evt;
      int rc;

      evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
      if (!pth_mutex_acquire (&entry_lock, 0, evt))
        {
          if (pth_event_occurred (evt))
            rc = gpg_error (GPG_ERR_TIMEOUT);
          else
            rc = gpg_error (GPG_ERR_INTERNAL);
          pth_event_free (evt, PTH_FREE_THIS);
          return rc;
        }
      pth_event_free (evt, PTH_FREE_THIS);
    }
  else
    {
      if (!pth_mutex_acquire (&entry_lock, 1, NULL))
        return gpg_error (GPG_ERR_LOCKED);
    }

  if (!pth_mutex_release (&entry_lock))
    log_error ("failed to release the entry lock at %d\n", __LINE__);
  return 0;
}
コード例 #4
0
ファイル: TSRM.c プロジェクト: ChadSikorra/php-src
/*
  Lock a mutex.
  A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
{
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
	EnterCriticalSection(mutexp);
	return 0;
#elif defined(GNUPTH)
	if (pth_mutex_acquire(mutexp, 0, NULL)) {
		return 0;
	}
	return -1;
#elif defined(PTHREADS)
	return pthread_mutex_lock(mutexp);
#elif defined(NSAPI)
	crit_enter(mutexp);
	return 0;
#elif defined(PI3WEB)
	return PISync_lock(mutexp);
#elif defined(TSRM_ST)
	return st_mutex_lock(mutexp);
#elif defined(BETHREADS)
	if (atomic_add(&mutexp->ben, 1) != 0)
		return acquire_sem(mutexp->sem);
	return 0;
#endif
}
コード例 #5
0
/* Initialize the mutex *PRIV.  If JUST_CHECK is true, only do this if
   it is not already initialized.  */
static int
mutex_pth_init (ath_mutex_t *priv, int just_check)
{
  int err = 0;

  if (just_check)
    pth_mutex_acquire (&check_init_lock, 0, NULL);
  if (!*priv || !just_check)
    {
      pth_mutex_t *lock = malloc (sizeof (pth_mutex_t));
      if (!lock)
	err = ENOMEM;
      if (!err)
	{
	  err = pth_mutex_init (lock);
	  if (err == FALSE)
	    err = errno;
	  else
	    err = 0;

	  if (err)
	    free (lock);
	  else
	    *priv = (ath_mutex_t) lock;
	}
    }
  if (just_check)
    pth_mutex_release (&check_init_lock);
  return err;
}
コード例 #6
0
ファイル: __handles.c プロジェクト: Azure/unixODBC-MSSQL
static int mutex_entry( pth_mutex_t *mutex )
{
    if ( !pth_init_called )
    {
        pth_init();
        pth_init_called = 1;
    }
    return pth_mutex_acquire( mutex, 0, NULL );
}
コード例 #7
0
ファイル: _logging.c プロジェクト: capensis/canopsis-edc
static int mutex_entry( void )
{
    if ( !pth_init_called )
    {
        pth_init();
        pth_init_called = 1;
    }
    return pth_mutex_acquire( &mutex_log, 0, NULL );
}
コード例 #8
0
ファイル: test_philo.c プロジェクト: Distrotech/pth
static void putdown(unsigned int k)
{
    pth_mutex_acquire(&(tab->mutex), FALSE, NULL);
    (tab->status)[k] = thinking;
    printstate();
    test((k + 1) % PHILNUM);
    test((k - 1 + PHILNUM) % PHILNUM);
    pth_mutex_release(&(tab->mutex));
    return;
}
コード例 #9
0
int
ath_mutex_lock (ath_mutex_t *lock)
{
  int ret = mutex_pth_init (lock, 1);
  if (ret)
    return ret;

  ret = pth_mutex_acquire ((pth_mutex_t *) *lock, 0, NULL);
  return ret == FALSE ? errno : 0;
}
コード例 #10
0
ファイル: test_philo.c プロジェクト: Distrotech/pth
static void pickup(unsigned int k)
{
    pth_mutex_acquire(&(tab->mutex), FALSE, NULL);
    (tab->status)[k] = hungry;
    printstate();
    if (!test(k))
        pth_cond_await(&((tab->condition)[k]), &(tab->mutex), NULL);
    printstate();
    pth_mutex_release(&(tab->mutex));
    return;
}
コード例 #11
0
ファイル: SDL_sysmutex.c プロジェクト: 3bu1/crossbridge
/* Lock the mutex */
int SDL_mutexP(SDL_mutex *mutex)
{
	if ( mutex == NULL ) {
		SDL_SetError("Passed a NULL mutex");
		return -1;
	}

	pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL);

	return(0);
}
コード例 #12
0
ファイル: b5-pth.c プロジェクト: alepharchives/cpc
void *
thread_routine(void *dummy)
{
    while(1) {
        pth_mutex_acquire(&mutex, FALSE, NULL);
        if(arg < 0)
            pth_cond_await(&c1, &mutex, NULL);
        res = arg;
        arg = -1;
        pth_mutex_release(&mutex);
        pth_cond_notify(&c2, FALSE);
    }
}
コード例 #13
0
ファイル: groupcache.cpp プロジェクト: Yazracor/knxd-snapshot
Array < eibaddr_t > GroupCache::LastUpdates (uint16_t start, uint8_t Timeout,
					     uint16_t & end, pth_event_t stop)
{
  Array < eibaddr_t > a;
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (Timeout, 0));

  do
    {
      if (pos < 0x100)
	{
	  if (pos < start && start < ((pos - 0x100) & 0xffff))
	    start = (pos - 0x100) & 0xffff;
	}
      else
	{
	  if (start < ((pos - 0x100) & 0xffff) || start > pos)
	    start = (pos - 0x100) & 0xffff;
	}
      TRACEPRINTF (t, 8, this, "LastUpdates start: %d pos: %d", start, pos);
      while (start != pos && !updates[start & 0xff])
	start++;
      if (start != pos)
	{
	  while (start != pos)
	    {
	      if (updates[start & 0xff])
		a.add (updates[start & 0xff]);
	      start++;
	    }
	  end = pos;
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return a;
	}
      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	{
	  end = pos;
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return a;
	}
      pth_event_concat (timeout, stop, NULL);
      pth_mutex_acquire (&mutex, 0, 0);
      pth_cond_await (&cond, &mutex, timeout);
      pth_mutex_release (&mutex);
      pth_event_isolate (timeout);
    }
  while (1);
}
コード例 #14
0
ファイル: TSRM.c プロジェクト: daniel-higa/php-src
/*
  Lock a mutex.
  A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
{/*{{{*/
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
	EnterCriticalSection(mutexp);
	return 0;
#elif defined(GNUPTH)
	if (pth_mutex_acquire(mutexp, 0, NULL)) {
		return 0;
	}
	return -1;
#elif defined(PTHREADS)
	return pthread_mutex_lock(mutexp);
#elif defined(TSRM_ST)
	return st_mutex_lock(mutexp);
#endif
}/*}}}*/
コード例 #15
0
ファイル: thr_pth.c プロジェクト: cptaffe/openldap
int
ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
{
	return( pth_mutex_acquire( mutex, 1, NULL ) ? 0 : errno );
}
コード例 #16
0
ファイル: groupcache.cpp プロジェクト: Yazracor/knxd-snapshot
GroupCacheEntry
  GroupCache::Read (eibaddr_t addr, unsigned Timeout, uint16_t age)
{
  TRACEPRINTF (t, 4, this, "GroupCacheRead %s %d %d",
	       FormatGroupAddr (addr)(), Timeout, age);
  bool rm = false;
  GroupCacheEntry *c;
  if (!enable)
    {
      GroupCacheEntry f;
      f.src = 0;
      f.dst = 0;
      TRACEPRINTF (t, 4, this, "GroupCache not enabled");
      return f;
    }

  c = find (addr);
  if (c && age && c->recvtime + age < time (0))
    rm = true;

  if (c && !rm)
    {
      TRACEPRINTF (t, 4, this, "GroupCache found: %s",
		   FormatEIBAddr (c->src)());
      return *c;
    }

  if (!Timeout)
    {
      GroupCacheEntry f;
      f.src = 0;
      f.dst = addr;
      TRACEPRINTF (t, 4, this, "GroupCache no entry");
      return f;
    }

  A_GroupValue_Read_PDU apdu;
  T_DATA_XXX_REQ_PDU tpdu;
  L_Data_PDU *l;
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (Timeout, 0));

  tpdu.data = apdu.ToPacket ();
  l = new L_Data_PDU (FakeL2);
  l->data = tpdu.ToPacket ();
  l->source = 0;
  l->dest = addr;
  l->AddrType = GroupAddress;
  layer3->send_L_Data (l);

  do
    {
      c = find (addr);
      rm = false;
      if (c && age && c->recvtime + age < time (0))
	rm = true;

      if (c && !rm)
	{
	  TRACEPRINTF (t, 4, this, "GroupCache found: %s",
		       FormatEIBAddr (c->src)());
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return *c;
	}

      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED && c)
	{
	  GroupCacheEntry gc;
	  gc.src = 0;
	  gc.dst = addr;
	  TRACEPRINTF (t, 4, this, "GroupCache reread timeout");
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return gc;
	}

      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	{
	  c = new GroupCacheEntry;
	  c->src = 0;
	  c->dst = addr;
	  c->recvtime = time (0);
	  add (c);
	  TRACEPRINTF (t, 4, this, "GroupCache timeout");
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return *c;
	}

      pth_mutex_acquire (&mutex, 0, 0);
      pth_cond_await (&cond, &mutex, timeout);
      pth_mutex_release (&mutex);
    }
  while (1);
}
コード例 #17
0
ファイル: FrSimThread.cpp プロジェクト: cainex/frsimulation
void FrSimThreadCondVar::lock()
{
	pth_mutex_acquire(&mutex, false, NULL);
	isLocked = true;
}
コード例 #18
0
ファイル: trustlist.c プロジェクト: CryptoBITDigital/gnupg-1
static void
lock_trusttable (void)
{
  if (!pth_mutex_acquire (&trusttable_lock, 0, NULL))
    log_fatal ("failed to acquire mutex in %s\n", __FILE__);
}
コード例 #19
0
ファイル: call-pinentry.c プロジェクト: HoraceWeebler/gnupg
/* Fork off the pin entry if this has not already been done.  Note,
   that this function must always be used to aquire the lock for the
   pinentry - we will serialize _all_ pinentry calls.
 */
static int
start_pinentry (ctrl_t ctrl)
{
  int rc;
  const char *pgmname;
  assuan_context_t ctx;
  const char *argv[5];
  int no_close_list[3];
  int i;
  pth_event_t evt;
  const char *tmpstr;
  unsigned long pinentry_pid;
  const char *value;

  evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
  if (!pth_mutex_acquire (&entry_lock, 0, evt))
    {
      if (pth_event_occurred (evt))
        rc = gpg_error (GPG_ERR_TIMEOUT);
      else
        rc = gpg_error (GPG_ERR_INTERNAL);
      pth_event_free (evt, PTH_FREE_THIS);
      log_error (_("failed to acquire the pinentry lock: %s\n"),
                 gpg_strerror (rc));
      return rc;
    }
  pth_event_free (evt, PTH_FREE_THIS);

  entry_owner = ctrl;

  if (entry_ctx)
    return 0; 

  if (opt.verbose)
    log_info ("starting a new PIN Entry\n");

#ifdef HAVE_W32_SYSTEM      
  fflush (stdout);
  fflush (stderr);
#endif
  if (fflush (NULL))
    {
#ifndef HAVE_W32_SYSTEM
      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
#endif
      log_error ("error flushing pending output: %s\n", strerror (errno));
      /* At least Windows XP fails here with EBADF.  According to docs
         and Wine an fflush(NULL) is the same as _flushall.  However
         the Wime implementaion does not flush stdin,stdout and stderr
         - see above.  Lets try to ignore the error. */
#ifndef HAVE_W32_SYSTEM
      return unlock_pinentry (tmperr);
#endif
    }

  if (!opt.pinentry_program || !*opt.pinentry_program)
    opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
    pgmname = opt.pinentry_program;
  if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
    pgmname = opt.pinentry_program;
  else
    pgmname++;

  /* OS X needs the entire file name in argv[0], so that it can locate
     the resource bundle.  For other systems we stick to the usual
     convention of supplying only the name of the program.  */
#ifdef __APPLE__
  argv[0] = opt.pinentry_program;
#else /*!__APPLE__*/
  argv[0] = pgmname;
#endif /*__APPLE__*/

  if (!opt.keep_display
      && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
    {
      argv[1] = "--display";
      argv[2] = value;
      argv[3] = NULL;
    }
  else
    argv[1] = NULL;
  
  i=0;
  if (!opt.running_detached)
    {
      if (log_get_fd () != -1)
        no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
      no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
    }
  no_close_list[i] = -1;

  rc = assuan_new (&ctx);
  if (rc)
    {
      log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
      return rc;
    }

  /* Connect to the pinentry and perform initial handshaking.  Note
     that atfork is used to change the environment for pinentry.  We
     start the server in detached mode to suppress the console window
     under Windows.  */
  rc = assuan_pipe_connect (ctx, opt.pinentry_program, argv,
			    no_close_list, atfork_cb, ctrl,
			    ASSUAN_PIPE_CONNECT_DETACHED);
  if (rc)
    {
      log_error ("can't connect to the PIN entry module: %s\n",
                 gpg_strerror (rc));
      assuan_release (ctx);
      return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
    }
  entry_ctx = ctx;

  if (DBG_ASSUAN)
    log_debug ("connection to PIN entry established\n");

  rc = assuan_transact (entry_ctx, 
                        opt.no_grab? "OPTION no-grab":"OPTION grab",
                        NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  value = session_env_getenv (ctrl->session_env, "GPG_TTY");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  value = session_env_getenv (ctrl->session_env, "TERM");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_ctype)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_messages)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }

  {
    /* Provide a few default strings for use by the pinentries.  This
       may help a pinentry to avoid implementing localization code.  */
    static struct { const char *key, *value; } tbl[] = {
      /* TRANSLATORS: These are labels for buttons etc used in
         Pinentries.  An underscore indicates that the next letter
         should be used as an accelerator.  Double the underscore for
         a literal one.  The actual to be translated text starts after
         the second vertical bar.  */
      { "ok",     N_("|pinentry-label|_OK") },
      { "cancel", N_("|pinentry-label|_Cancel") },
      { "prompt", N_("|pinentry-label|PIN:") },
      { NULL, NULL}
    };
    char *optstr;
    int idx;
    const char *s, *s2;

    for (idx=0; tbl[idx].key; idx++)
      {
        s = _(tbl[idx].value);
        if (*s == '|' && (s2=strchr (s+1,'|')))
          s = s2+1;
        if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
          return unlock_pinentry (out_of_core ());
        assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                         NULL);
        xfree (optstr);
      }
  }

  
  /* Tell the pinentry the name of a file it shall touch after having
     messed with the tty.  This is optional and only supported by
     newer pinentries and thus we do no error checking. */
  tmpstr = opt.pinentry_touch_file;
  if (tmpstr && !strcmp (tmpstr, "/dev/null"))
    tmpstr = NULL;
  else if (!tmpstr)
    tmpstr = get_agent_socket_name ();
  if (tmpstr)
    {
      char *optstr;
      
      if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
        ;
      else
        {
          assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                           NULL);
          xfree (optstr);
        }
    }


  /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
     it will send the pid back and we will use an inquire to notify
     our client.  The client may answer the inquiry either with END or
     with CAN to cancel the pinentry. */
  rc = assuan_transact (entry_ctx, "GETINFO pid", 
                        getinfo_pid_cb, &pinentry_pid,
                        NULL, NULL, NULL, NULL);
  if (rc)
    {
      log_info ("You may want to update to a newer pinentry\n");
      rc = 0;
    }
  else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
    log_error ("pinentry did not return a PID\n");
  else
    {
      rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
      if (gpg_err_code (rc) == GPG_ERR_CANCELED)
        return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
      rc = 0;
    }

  return 0;
}
コード例 #20
0
ファイル: main.cpp プロジェクト: dizel3d/disser
int main(int argc, char *argv[])
{
	if (argc < 5) {
		return 1;
	}

	auto processNum = 4;
	auto threadNum = atoi(argv[4]);
	auto dtime = atol(argv[3]) * 1000;
	auto isPth = std::string(argv[2]) == "pth";
	auto taskNum = atoi(argv[1]);
	long cycles = 0;

	switch(taskNum) {
	case 1: task = task1; break;
	case 2: task = task2; break;
	case 3: task = task3; break;
	}

	time_start();

	for (auto i = 0; i < processNum; ++i) {
		if (fork() != 0) {
			continue;
		}

		if (isPth) {
			pth_init();

			pth_attr_t attr = pth_attr_new();
			pth_attr_set(attr, PTH_ATTR_NAME, "task");
			pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 64*1024);
			pth_attr_set(attr, PTH_ATTR_JOINABLE, true);

			pth_mutex_t mutex;
			pth_mutex_init(&mutex);
			pth_cond_init(&pthCond);

			while (time_stop() < dtime) {
				for (auto i = workingNum; i < threadNum; ++i) {
					++workingNum;
					pth_spawn(attr, task, &isPth);
				}

				int rc;
				if ((rc = pth_mutex_acquire(&mutex, FALSE, NULL)) != 0) {
					std::cout << "pthread_mutex_lock " << rc << " " << strerror(rc) << std::endl;
					return 3;
				}
				if (workingNum == threadNum) {
					if ((rc = pth_cond_await(&pthCond, &mutex, NULL)) != 0) {
						std::cout << "pthread_cond_wait " << rc << " " << strerror(rc) << std::endl;
						return 3;
					}
				}
				if ((rc = pth_mutex_release(&mutex)) != 0) {
					std::cout << "pthread_mutex_unlock " << rc << " " << strerror(rc) << std::endl;
					return 3;
				}
				cycles += threadNum - workingNum;
			}
		}
		else {
			pthread_attr_t attr;
			pthread_attr_setstacksize(&attr, 64*1024);

			pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
			pthread_mutexattr_t mutexattr;
			pthread_mutex_init(&mutex, &mutexattr);
			pthread_condattr_t condattr;
			pthread_cond_init(&cond, &condattr);

			pthread_t pid;
			while (time_stop() < dtime) {
				for (auto i = workingNum; i < threadNum; ++i) {
					++workingNum;
					if (pthread_create(&pid, NULL, task, &isPth) == -1) {
						return 2;
					}
				}

				int rc;
				if ((rc = pthread_mutex_lock(&mutex)) != 0) {
					std::cout << "pthread_mutex_lock " << rc << " " << strerror(rc) << std::endl;
					return 3;
				}
				if (workingNum == threadNum) {
					if ((rc = pthread_cond_wait(&cond, &mutex)) != 0) {
						std::cout << "pthread_cond_wait " << rc << " " << strerror(rc) << std::endl;
						return 3;
					}
				}
				if ((rc = pthread_mutex_unlock(&mutex)) != 0) {
					std::cout << "pthread_mutex_unlock " << rc << " " << strerror(rc) << std::endl;
					return 3;
				}
				//pthread_join(pids.front(), NULL);
				//pids.pop_front();
				cycles += threadNum - workingNum;
			}
		}

		std::cout << cycles << std::endl;

		return 0;
	}
	for (auto i = 0; i < processNum; ++i) {
		wait(NULL);
	}

	return 0;
}