コード例 #1
0
ファイル: offload_util.cpp プロジェクト: 0day-ci/gcc
// Run once
static BOOL CALLBACK __offload_run_once_wrapper(
    PINIT_ONCE initOnce,
    PVOID parameter,
    PVOID *context
)
{
    void (*init_routine)(void) = (void(*)(void)) parameter;
    init_routine();
    return true;
}
コード例 #2
0
ファイル: _once_stub.c プロジェクト: AhmadTux/freebsd
/* This implements pthread_once() for the single-threaded case. */
static int
_libc_once(pthread_once_t *once_control, void (*init_routine)(void))
{

	if (once_control->state == PTHREAD_DONE_INIT)
		return (0);
	init_routine();
	once_control->state = PTHREAD_DONE_INIT;
	return (0);
}
コード例 #3
0
ファイル: pthread_once.c プロジェクト: Drakey83/steamlink-sdk
int
__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
{
  for (;;)
    {
      int oldval;
      int newval;

      /* Pseudo code:
	 newval = __fork_generation | 1;
	 oldval = *once_control;
	 if ((oldval & 2) == 0)
	   *once_control = newval;
	 Do this atomically.  */
      do
	{
	  newval = __fork_generation | 1;
	  oldval = *once_control;
	  if (oldval & 2)
	    break;
	} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);

      /* Check if the initializer has already been done.  */
      if ((oldval & 2) != 0)
	return 0;

      /* Check if another thread already runs the initializer.	*/
      if ((oldval & 1) == 0)
	break;

      /* Check whether the initializer execution was interrupted by a fork.  */
      if (oldval != newval)
	break;

      /* Same generation, some other thread was faster. Wait.  */
      lll_futex_wait (once_control, oldval, LLL_PRIVATE);
    }

  /* This thread is the first here.  Do the initialization.
     Register a cleanup handler so that in case the thread gets
     interrupted the initialization can be restarted.  */
  pthread_cleanup_push (clear_once_control, once_control);

  init_routine ();

  pthread_cleanup_pop (0);

  /* Say that the initialisation is done.  */
  *once_control = __fork_generation | 2;

  /* Wake up all other threads.  */
  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);

  return 0;
}
コード例 #4
0
ファイル: pthread.c プロジェクト: kstraube/hysim
int pthread_once(
    pthread_once_t *once_control, void (*init_routine)(void))
{
    pthread_initialize();
    if (once_control == NULL || init_routine == NULL)
        return_errno(EINVAL, EINVAL);
    if (*once_control != 1)
        init_routine();
    *once_control = 1;
    return OK;
}
コード例 #5
0
ファイル: pthread.c プロジェクト: Archer-sys/mpv
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
    BOOL pending;
    if (!InitOnceBeginInitialize(once_control, 0, &pending, NULL))
        abort();
    if (pending) {
        init_routine();
        InitOnceComplete(once_control, 0, NULL);
    }
    return 0;
}
コード例 #6
0
ファイル: pthread.c プロジェクト: patrickelectric/predator
/**
 * Once-only initialization.
 * @param  once_control The control variable which initialized to PTHREAD_ONCE_INIT.
 * @param  init_routine The initialization code which executed at most once.
 * @return Always return 0.
 */
int pthread_once(pthread_once_t *once_control, void (* init_routine)(void))
{
    if (atomic_cmpxchg((long volatile *) once_control, 1, 0) == 0) {
        init_routine();
        *(volatile int *) once_control = 2;
    } else {
        while(*(volatile int *) once_control != 2)
            SwitchToThread();
    }

    return 0;
}
コード例 #7
0
ファイル: os_once.c プロジェクト: 3rf/mongo
/*
 * __wt_init_once_callback --
 *	Global initialization, run once.
 */
BOOL CALLBACK _wt_init_once_callback(
    _Inout_      PINIT_ONCE InitOnce,
    _Inout_opt_  PVOID Parameter,
    _Out_opt_    PVOID *Context
    )
{
	void(*init_routine)(void) = Parameter;

	init_routine();

	return (TRUE);
}
コード例 #8
0
ファイル: pthreads_win32.c プロジェクト: Ferada/sbcl
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
  if (PTHREAD_ONCE_INIT == *once_control) {
    pthread_mutex_lock(&once_mutex);
    if (PTHREAD_ONCE_INIT == *once_control) {
      init_routine();
      *once_control = 42;
    }
    pthread_mutex_unlock(&once_mutex);
  }
  return 0;
}
コード例 #9
0
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
  if(compare_and_swap((void *)once_control, (void *)0, (void *)1))
		init_routine();
  //TODO: "The pthread_once() function is not a cancellation point.
	//However, if init_routine is a cancellation point and is canceled,
	//the effect on once_control shall be as if pthread_once() was never called."
	//TODO: "The pthread_once() function may fail if:
	//[EINVAL]
	//	If either once_control or init_routine is invalid. (Question: what does 'invalid' mean?)

	return 0;
}
コード例 #10
0
ファイル: acl_pthread.c プロジェクト: LazyPlanet/acl
int acl_pthread_once(acl_pthread_once_t *once_control,
	void (*init_routine)(void))
{
	int   n = 0;

	if (once_control == NULL || init_routine == NULL) {
		acl_set_error(ACL_EINVAL);
		return ACL_EINVAL;
	}

	/* 只有第一个调用 InterlockedCompareExchange 的线程才会执行
	 * init_routine, 后续线程永远在 InterlockedCompareExchange
	 * 外运行,并且一直进入空循环直至第一个线程执行 init_routine
	 * 完毕并且将 *once_control 重新赋值, 只有在多核环境中多个线程
	 * 同时运行至此时才有可能出现短暂的后续线程空循环现象,如果
	 * 多个线程顺序至此,则因为 *once_control 已经被第一个线程重新
	 * 赋值而不会进入循环体内只所以如此处理,是为了保证所有线程在
	 * 调用 acl_pthread_once 返回前 init_routine 必须被调用且仅能
	 * 被调用一次, 但在VC6下,InterlockedCompareExchange 接口定义
	 * 有些怪异,需要做硬性指定参数类型,参见 <Windows 高级编程指南>
	 * Jeffrey Richter, 366 页
	 */
	while (1) {
#ifdef MS_VC6
		LONG prev = InterlockedCompareExchange((PVOID) once_control,
			(PVOID) 1, (PVOID) ACL_PTHREAD_ONCE_INIT);
#else
		LONG prev = InterlockedCompareExchange(
			once_control, 1, ACL_PTHREAD_ONCE_INIT);
#endif
		if (prev == 2)
			return 0;
		else if (prev == 0) {
			/* 只有第一个线程才会至此 */
			init_routine();
			/* 将 *conce_control 重新赋值以使后续线程不进入 while
			 * 循环或从 while 循环中跳出
			 */
			InterlockedExchange(once_control, 2);
			return 0;
		} else {
			acl_assert(prev == 1);

			/* 防止空循环过多地浪费CPU */
			Sleep(1);  /** sleep 1ms */
		}
	}
	return 1;  /* 不可达代码,避免编译器报警告 */
}
コード例 #11
0
ファイル: thread.c プロジェクト: libimobiledevice/libusbmuxd
void thread_once(thread_once_t *once_control, void (*init_routine)(void))
{
#ifdef WIN32
	while (InterlockedExchange(&(once_control->lock), 1) != 0) {
		Sleep(1);
	}
	if (!once_control->state) {
		once_control->state = 1;
		init_routine();
	}
	InterlockedExchange(&(once_control->lock), 0);
#else
	pthread_once(once_control, init_routine);
#endif
}
コード例 #12
0
ファイル: uthread_once.c プロジェクト: 5432935/crossbridge
int
_pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
{
	if (once_control->state == PTHREAD_NEEDS_INIT) {
		if (_thread_initial == NULL)
			_thread_init();
		_pthread_mutex_lock(&(once_control->mutex));
		if (once_control->state == PTHREAD_NEEDS_INIT) {
			init_routine();
			once_control->state = PTHREAD_DONE_INIT;
		}
		_pthread_mutex_unlock(&(once_control->mutex));
	}
	return (0);
}
コード例 #13
0
ファイル: uc_pthread.cpp プロジェクト: nandohca/kista
int UC_posix_class::uc_pthread_once(uc_pthread_once_t *once_control, void (*init_routine)(void)){
	if (once_control == NULL) {
		 return -1;
	}

	if (init_routine == NULL) {
		 return -1;
	}

	if (*once_control) {
		 init_routine();
	}

	(*once_control) = 0;
	return 0;
}
コード例 #14
0
ファイル: uthread_once.c プロジェクト: sofuture/bitrig
int
pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
{
	int ret;

	if (once_control->state == PTHREAD_NEEDS_INIT) {
		if ((ret = pthread_mutex_lock(&(once_control->mutex))) != 0)
			return ret;
		if (once_control->state == PTHREAD_NEEDS_INIT) {
			init_routine();
			once_control->state = PTHREAD_DONE_INIT;
		}
		pthread_mutex_unlock(&(once_control->mutex));
	}
	return (0);
}
コード例 #15
0
ファイル: mutex.c プロジェクト: 32bitmicro/newlib-nano-1.0
int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
{
  /* flag for doing the condition broadcast outside of mutex */
  int state_changed;

  /* Test without locking first for speed */
  if (*once_control == DONE) {
    READ_MEMORY_BARRIER();
    return 0;
  }
  /* Lock and test again */

  state_changed = 0;

  pthread_mutex_lock(&once_masterlock);

  /* If this object was left in an IN_PROGRESS state in a parent
     process (indicated by stale generation field), reset it to NEVER. */
  if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
    *once_control = NEVER;

  /* If init_routine is being called from another routine, wait until
     it completes. */
  while ((*once_control & 3) == IN_PROGRESS) {
    pthread_cond_wait(&once_finished, &once_masterlock);
  }
  /* Here *once_control is stable and either NEVER or DONE. */
  if (*once_control == NEVER) {
    *once_control = IN_PROGRESS | fork_generation;
    pthread_mutex_unlock(&once_masterlock);
    pthread_cleanup_push(pthread_once_cancelhandler, once_control);
    init_routine();
    pthread_cleanup_pop(0);
    pthread_mutex_lock(&once_masterlock);
    WRITE_MEMORY_BARRIER();
    *once_control = DONE;
    state_changed = 1;
  }
  pthread_mutex_unlock(&once_masterlock);

  if (state_changed)
    pthread_cond_broadcast(&once_finished);

  return 0;
}
コード例 #16
0
ファイル: pthread.c プロジェクト: dlts200466/PowerSupply
int pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
{
	RT_ASSERT(once_control != RT_NULL);
	RT_ASSERT(init_routine != RT_NULL);

	rt_enter_critical();
	if (!(*once_control))
	{
		/* call routine once */
		*once_control = 1;
		rt_exit_critical();

		init_routine();
	}
	rt_exit_critical();

	return 0;
}
コード例 #17
0
ファイル: pthread_once.c プロジェクト: vocho/openqnx
int __pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) {
	int					ret;

	if((ret = pthread_mutex_lock(&once_control->__mutex)) != EOK) {
		return (once_control->__once != 0) ? EOK : ret;
	}

	if( once_control->__once == 0 ) {
		pthread_cleanup_push(pthread_once_cancel, &once_control->__mutex);
		init_routine();
		pthread_cleanup_pop(0);
		once_control->__once = 1;
	}

	if(pthread_mutex_unlock(&once_control->__mutex) == EOK) {
		pthread_mutex_destroy(&once_control->__mutex);
	}
	return EOK;
}
コード例 #18
0
ファイル: compat.c プロジェクト: MerlijnWajer/torsocks
/*
 * Call the given routine once, and only once. tsocks_once returning
 * guarantees that the routine has succeded.
 */
void tsocks_once(tsocks_once_t *o, void (*init_routine)(void))
{

	/* Why, yes, pthread_once(3P) exists. Said routine requires linking in a
	 * real pthread library on Linux, while this does not and will do the right
	 * thing even with the stub implementation. */
	assert(o);

	/* This looks scary and incorrect, till you realize that the
	 * pthread_mutex routines include memory barriers. */
	if (!o->once) {
		return;
	}
	tsocks_mutex_lock(&o->mutex);
	if (o->once) {
		init_routine();
		o->once = 0;
	}
	tsocks_mutex_unlock(&o->mutex);
}
コード例 #19
0
ファイル: once.c プロジェクト: BhargavKola/xenomai-forge
/**
 * Execute an initialization routine.
 *
 * This service may be used by libraries which need an initialization function
 * to be called only once.
 *
 * The function @a init_routine will only be called, with no argument, the first
 * time this service is called specifying the address @a once.
 *
 * @return 0 on success;
 * @return an error number if:
 * - EINVAL, the object pointed to by @a once is invalid (it must have been
 *   initialized with PTHREAD_ONCE_INIT).
 *
 * @see
 * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_once.html">
 * Specification.</a>
 *
 */
int pthread_once(pthread_once_t * once, void (*init_routine) (void))
{
	spl_t s;

	xnlock_get_irqsave(&nklock, s);

	if (!pse51_obj_active(once, PSE51_ONCE_MAGIC, pthread_once_t)) {
		xnlock_put_irqrestore(&nklock, s);
		return EINVAL;
	}

	if (!once->routine_called) {
		init_routine();
		/* If the calling thread is canceled while executing init_routine,
		   routine_called will not be set to 1. */
		once->routine_called = 1;
	}

	xnlock_put_irqrestore(&nklock, s);

	return 0;
}
コード例 #20
0
VCOS_STATUS_T vcos_once(VCOS_ONCE_T *once_control,
                        void (*init_routine)(void))
{
   /* In order to be thread-safe we need to re-test *once_control
    * inside the lock. The outer test is basically an optimization
    * so that once it is initialized we don't need to waste time
    * trying to acquire the lock.
    */

   if ( *once_control == 0 )
   {
       vcos_global_lock();
       if ( *once_control == 0 )
       {
           init_routine();
           *once_control = 1;
       }
       vcos_global_unlock();
   }

   return VCOS_SUCCESS;
}
コード例 #21
0
// This implementation doesn't support thread-cancelation nor fork during
// the execution of init_routine().
int pthread_once(pthread_once_t  *once_control, void (*init_routine)(void)) {
  // pthread_once always returns 0.

  if (once_control == NULL || init_routine == NULL) {
    return 0;
  }

  // Double-checked locking is not a good solution in general, but it works
  // in this case in C.
  if (*once_control != PTHREAD_ONCE_INIT) {
    return 0;
  }

  pthread_mutex_lock(&once_lock);

  if (*once_control == PTHREAD_ONCE_INIT) {
    init_routine();
    *once_control = PTHREAD_ONCE_INIT + 1;
  }

  pthread_mutex_unlock(&once_lock);

  return 0;
}
コード例 #22
0
ファイル: pthread.c プロジェクト: kstraube/hysim
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
{
  if(atomic_swap(once_control,1) == 0)
    init_routine();
  return 0;
}
コード例 #23
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
int pthread_once(pthread_once_t* once, void (*init_routine)())
{
	if(cpu_CAS((volatile intptr_t*)once, 0, 1))
		init_routine();
	return 0;
}
コード例 #24
0
ファイル: pthread_once.c プロジェクト: KubaKaszycki/kklibc
__pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
{
  while (1)
    {
      int val, newval;

      /* We need acquire memory order for this load because if the value
         signals that initialization has finished, we need to see any
         data modifications done during initialization.  */
      val = atomic_load_acquire (once_control);
      do
	{
	  /* Check if the initialization has already been done.  */
	  if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0))
	    return 0;

	  /* We try to set the state to in-progress and having the current
	     fork generation.  We don't need atomic accesses for the fork
	     generation because it's immutable in a particular process, and
	     forked child processes start with a single thread that modified
	     the generation.  */
	  newval = __fork_generation | __PTHREAD_ONCE_INPROGRESS;
	  /* We need acquire memory order here for the same reason as for the
	     load from once_control above.  */
	}
      while (__glibc_unlikely (!atomic_compare_exchange_weak_acquire (
	  once_control, &val, newval)));

      /* Check if another thread already runs the initializer.	*/
      if ((val & __PTHREAD_ONCE_INPROGRESS) != 0)
	{
	  /* Check whether the initializer execution was interrupted by a
	     fork.  We know that for both values, __PTHREAD_ONCE_INPROGRESS
	     is set and __PTHREAD_ONCE_DONE is not.  */
	  if (val == newval)
	    {
	      /* Same generation, some other thread was faster.  Wait and
		 retry.  */
	      futex_wait_simple ((unsigned int *) once_control,
				 (unsigned int) newval, FUTEX_PRIVATE);
	      continue;
	    }
	}

      /* This thread is the first here.  Do the initialization.
	 Register a cleanup handler so that in case the thread gets
	 interrupted the initialization can be restarted.  */
      pthread_cleanup_push (clear_once_control, once_control);

      init_routine ();

      pthread_cleanup_pop (0);


      /* Mark *once_control as having finished the initialization.  We need
         release memory order here because we need to synchronize with other
         threads that want to use the initialized data.  */
      atomic_store_release (once_control, __PTHREAD_ONCE_DONE);

      /* Wake up all other threads.  */
      futex_wake ((unsigned int *) once_control, INT_MAX, FUTEX_PRIVATE);
      break;
    }

  return 0;
}