Exemple #1
0
/**
 * Atomically wait for the semaphore to become non-zero (if needed),
 * then decrements it.
 */
void vlc_sem_wait (vlc_sem_t *sem)
{
    int val;

#if defined(__APPLE__)
    if (likely(semaphore_wait(*sem) == KERN_SUCCESS))
        return;

    val = EINVAL;
#else
    do
        if (likely(sem_wait (sem) == 0))
            return;
    while ((val = errno) == EINTR);
#endif

    VLC_THREAD_ASSERT ("locking semaphore");
}
Exemple #2
0
void
_dispatch_thread_semaphore_wait(_dispatch_thread_semaphore_t sema)
{
#if USE_MACH_SEM
    semaphore_t s4 = (semaphore_t)sema;
    kern_return_t kr;
    do {
        kr = semaphore_wait(s4);
    } while (slowpath(kr == KERN_ABORTED));
    DISPATCH_SEMAPHORE_VERIFY_KR(kr);
#elif USE_POSIX_SEM
    sem_t s4 = (sem_t)sema;
    int ret;
    do {
        ret = sem_wait(&s4);
    } while (slowpath(ret != 0));
    DISPATCH_SEMAPHORE_VERIFY_RET(ret);
#endif
}
thread_t *thread_new_sized(const char *name, size_t work_queue_capacity) {
  assert(name != NULL);
  assert(work_queue_capacity != 0);

  thread_t *ret = osi_calloc(sizeof(thread_t));
  if (!ret)
    goto error;

  ret->reactor = reactor_new();
  if (!ret->reactor)
    goto error;

  ret->work_queue = fixed_queue_new(work_queue_capacity);
  if (!ret->work_queue)
    goto error;

  // Start is on the stack, but we use a semaphore, so it's safe
  struct start_arg start;
  start.start_sem = semaphore_new(0);
  if (!start.start_sem)
    goto error;

  strncpy(ret->name, name, THREAD_NAME_MAX);
  start.thread = ret;
  start.error = 0;
  pthread_create(&ret->pthread, NULL, run_thread, &start);
  semaphore_wait(start.start_sem);
  semaphore_free(start.start_sem);

  if (start.error)
    goto error;

  return ret;

error:;
  if (ret) {
    fixed_queue_free(ret->work_queue, osi_free);
    reactor_free(ret->reactor);
  }
  osi_free(ret);
  return NULL;
}
Exemple #4
0
inline int
fast_sendrecv_m (task_id dst_id, u32 arg1, u32 arg2, u32 *r_arg1, u32 *r_arg2)
{
  quest_tss *src = lookup_TSS (str ());
  quest_tss *dst = lookup_TSS (dst_id);

  semaphore_wait (&dst->Msem, 1, -1);
  dst->M[0] = arg1;
  dst->M[1] = arg2;
  semaphore_signal (&src->Msem, 1);
  ltr (dst_id);
  asm volatile ("call _sw_ipc"
                :"+S" (src), "+D" (dst)
                :
                :"eax", "ebx", "ecx", "edx", "cc", "memory");
  /* after _sw_ipc dst and src are swapped */
  *r_arg1 = dst->M[0];
  *r_arg2 = dst->M[1];
  return 0;
}
Exemple #5
0
int
fprintf(FILE *fp, const char *fmt, ...)
{
	kern_return_t kern_res;
	va_list ap;
	if (!_init)
	{
		_init++;
		MACH_CALL(semaphore_create(mach_task_self(), 
					   &lock, 
					   SYNC_POLICY_FIFO,
					   1),
			  kern_res);
	}
	MACH_CALL(semaphore_wait(lock), kern_res);
	va_start(ap, fmt);
	vfprintf(fp, fmt, ap);
	va_end(ap);
	MACH_CALL(semaphore_signal(lock), kern_res);
}
Exemple #6
0
message_t *msg_receive(void)
{
    message_t *msg = NULL;
    const uint32_t pid = proc_ctrl_get_curr_pid();


    if (0 < msg_list[pid].nbr_in_que) {
        // Critical region starts...
        semaphore_wait(&g_mutex_msg_list);
        
        msg = msg_list[pid].next_msg;
        msg_list[pid].next_msg = msg_list[pid].next_msg->next_msg;
        msg_list[pid].nbr_in_que -= 1;
        
        // Critical regions ends...
        semaphore_signal(&g_mutex_msg_list);    
    }
    
    return msg;
}
Exemple #7
0
DECLARE_TEST( semaphore, initialize )
{
	semaphore_t sem;

	semaphore_initialize( &sem, 0 );
	EXPECT_FALSE( semaphore_try_wait( &sem, 100 ) );
	semaphore_destroy( &sem );

	semaphore_initialize( &sem, 1 );
	EXPECT_TRUE( semaphore_try_wait( &sem, 100 ) );
	semaphore_destroy( &sem );

	semaphore_initialize( &sem, 2 );
	EXPECT_TRUE( semaphore_wait( &sem ) );
	EXPECT_TRUE( semaphore_try_wait( &sem, 100 ) );
	EXPECT_FALSE( semaphore_try_wait( &sem, 100 ) );
	semaphore_destroy( &sem );
	
	return 0;
}
Exemple #8
0
enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout)
{
    if(i2c_nr_stages == 0)
        return I2C_ERROR;
    i2c_stage[i2c_nr_stages - 1].dma.cmd |= BM_APB_CHx_CMD_SEMAPHORE | BM_APB_CHx_CMD_IRQONCMPLT;

    BF_CLR(I2C_CTRL1, ALL_IRQ);
    imx233_dma_reset_channel(APB_I2C);
    imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true);
    imx233_icoll_enable_interrupt(INT_SRC_I2C_ERROR, true);
    imx233_dma_enable_channel_interrupt(APB_I2C, true);
    imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma);

    enum imx233_i2c_error_t ret;
    if(semaphore_wait(&i2c_sema, timeout) == OBJ_WAIT_TIMEDOUT)
    {
        imx233_dma_reset_channel(APB_I2C);
        imx233_i2c_reset();
        ret = I2C_TIMEOUT;
    }
    else if(BF_RD(I2C_CTRL1, MASTER_LOSS_IRQ))
        ret = I2C_MASTER_LOSS;
    else if(BF_RD(I2C_CTRL1, NO_SLAVE_ACK_IRQ))
    {
        /* the core doesn't like this error, this is a workaround to prevent lock up */
#if IMX233_SUBTARGET >= 3780
        BF_SET(I2C_CTRL1, CLR_GOT_A_NAK);
#endif
        imx233_dma_reset_channel(APB_I2C);
        imx233_i2c_reset();
        ret = I2C_NO_SLAVE_ACK;
    }
    else if(BF_RD(I2C_CTRL1, EARLY_TERM_IRQ))
        ret = I2C_SLAVE_NAK;
    else
        ret = imx233_i2c_finalize();
    /* sleep */
    BF_SET(I2C_CTRL0, CLKGATE);
    mutex_unlock(&i2c_mutex);
    return ret;
}
Exemple #9
0
static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size)
{
    if (size > 0x10) RET_ERR(0);
    mmc_discard_irq();
    SDCI_DMASIZE = size;
    SDCI_DMACOUNT = 1;
    SDCI_DMAADDR = dest;
    SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST;
    commit_discard_dcache();
    PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_REG)
                           | SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_RES_TYPE_R1
                           | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR,
                             MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_READ
                           | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc)
                           | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc),
                             NULL, CEATA_COMMAND_TIMEOUT), 2, 1);
    if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000)
        == OBJ_WAIT_TIMEDOUT) RET_ERR(2);
    PASS_RC(mmc_dsta_check_data_success(), 2, 3);
    return 0;
}
int usb_drv_send(int ep, void *ptr, int len)
{
    logf("usb_drv_send(%d,%x,%d): ", ep, (int)ptr, len);

    ep &= 0x7f;

    if (ep == 0 && got_set_configuration) {
        got_set_configuration = 0;
        if (len != 0)
            panicf("usb_drv_send: GSC, but len!=0");
        /* Tell the HW we handled the request */
        USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE;
        return 0;
    }

    ep_send(ep, ptr, len);
    if (semaphore_wait(&endpoints[ep][0].complete, HZ) == OBJ_WAIT_TIMEDOUT)
        logf("send timed out!\n");

    return endpoints[ep][0].rc;
}
Exemple #11
0
static void *timer_func(void *arg)
{
	timer_thread = mach_thread_self();
	timer_thread_active = true;
	
	while (timer_thread_active) {
		clock_sleep(system_clock, TIME_ABSOLUTE, wakeup_time, NULL);
		semaphore_wait(wakeup_time_sem);
	   
		tm_time_t system_time;
		
		timer_current_time(system_time);
		if (timer_cmp_time(wakeup_time, system_time) < 0) {
			wakeup_time = wakeup_time_max;
			SetInterruptFlag(INTFLAG_TIMER);
			TriggerInterrupt();
		}
		semaphore_signal(wakeup_time_sem);
	}
    return NULL;
}
Exemple #12
0
/*******************************************************************************
Name        : EnterCriticalSection
Description : Used to protect critical sections of Init/Open/Close/Term
Parameters  : None
Assumptions :
Limitations :
Returns     : Nothing
*******************************************************************************/
static void EnterCriticalSection(void)
{
    static BOOL InstancesAccessControlInitialized = FALSE;

#if !defined(ST_OSLINUX)
    task_lock();
#endif

    if (!InstancesAccessControlInitialized)
    {

        InstancesAccessControlInitialized = TRUE;
        InstancesAccessControl_p = semaphore_create_fifo(1);

    }
#if !defined(ST_OSLINUX)
    task_unlock();
#endif


    semaphore_wait(InstancesAccessControl_p);
}
Exemple #13
0
bool
lua_acquire_execution_right(lua_t* env, bool force) {
	uint64_t self = thread_id();
	if (atomic_load64(&env->executing_thread) == self) {
		++env->executing_count;
		return true;
	}
	if (force) {
		semaphore_wait(&env->execution_right);
		atomic_store64(&env->executing_thread, self);
		FOUNDATION_ASSERT(env->executing_count == 0);
		++env->executing_count;
		return true;
	}
	if (semaphore_try_wait(&env->execution_right, 0)) {
		atomic_store64(&env->executing_thread, self);
		FOUNDATION_ASSERT(env->executing_count == 0);
		++env->executing_count;
		return true;
	}
	return false;
}
void handler()
{
    int i;
    for(i=0; i < 5; i++)
    {
        /* If you remove this protection, you should be able to see different
         * out of every time you run this program.  With this protection, you
         * should always be able to see result to be 151402.656521 */
        semaphore_wait(counter_mutex);       /* down semaphore */

        /* START CRITICAL REGION */
        int j;
        for (j = 0; j < 1000; j++) {
            result = result + sin(counter) * tan(counter);
        }
        counter++;
        /* END CRITICAL REGION */    

        semaphore_signal(counter_mutex);       /* up semaphore */
    }
    mythread_exit(); /* exit thread */
}
Exemple #15
0
uint32_t msg_send(message_t *msg)
{
    uint32_t ret = 0;


    ASSERT(NULL != msg);
    // ASSERT if the msg not pointing on the heap

    ASSERT(PID_IDLE != msg->receiver);
    ASSERT(HIGH_PID >= msg->receiver);
    ASSERT(msg_none_1 < msg->id && msg->id < msg_none_2);
    ret = msg->receiver;

    // Critical region starts...
    semaphore_wait(&g_mutex_msg_list);
    if (0 == msg_list[msg->receiver].nbr_in_que) {
        msg_list[msg->receiver].next_msg = msg;
        msg_list[msg->receiver].last_msg = msg;
    }
    else {
        msg_list[msg->receiver].last_msg->next_msg = msg;
        msg_list[msg->receiver].last_msg = msg;
    }
    
    msg_list[msg->receiver].nbr_in_que += 1;
    msg->next_msg = NULL;

    // semaphore_signal will generate a context switch. Make sure that the
    // receiving process is in state ready.
    if (msg->receiver != proc_ctrl_get_curr_pid()) {
        proc_ctrl_change_state(msg->receiver, ready);
    }
    
    // Critical regions ends...
    semaphore_signal(&g_mutex_msg_list);
    
    msg = NULL;
    return ret;
}
thread_t *thread_new(const char *name) {
  assert(name != NULL);

  // Start is on the stack, but we use a semaphore, so it's safe
  thread_t *ret = calloc(1, sizeof(thread_t));
  if (!ret)
    goto error;

  ret->reactor = reactor_new();
  if (!ret->reactor)
    goto error;

  ret->work_queue = fixed_queue_new(WORK_QUEUE_CAPACITY);
  if (!ret->work_queue)
    goto error;

  struct start_arg start;
  start.start_sem = semaphore_new(0);
  if (!start.start_sem)
    goto error;

  strncpy(ret->name, name, THREAD_NAME_MAX);
  start.thread = ret;
  start.error = 0;
  pthread_create(&ret->pthread, NULL, run_thread, &start);
  semaphore_wait(start.start_sem);
  semaphore_free(start.start_sem);
  if (start.error)
    goto error;
  return ret;

error:;
  if (ret) {
    fixed_queue_free(ret->work_queue, free);
    reactor_free(ret->reactor);
  }
  free(ret);
  return NULL;
}
Exemple #17
0
char* file_queue_get()
{
  char* result;

  semaphore_wait(&used_slots);
  mutex_lock(&queue_mutex);

  if (queue_head == queue_tail) // queue is empty
  {
    result = NULL;
  }
  else
  {
    result = file_queue[queue_head].path;
    queue_head = (queue_head + 1) % (MAX_QUEUED_FILES + 1);
  }

  mutex_unlock(&queue_mutex);
  semaphore_release(&unused_slots);

  return result;
}
static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
{
    struct endpoint_t *ep;
    int ep_num = EP_NUM(endpoint);
    
    if (ep_num == 0)
        ep = &ctrlep[DIR_IN];
    else
        ep = &endpoints[ep_num];

    ep->buf = ptr;
    ep->len = ep->cnt = length;
    
    if (block)
        ep->block = true;
    else
        ep->block = false;
    
    switch (ep->type)
    {
        case USB_ENDPOINT_XFER_CONTROL:                     
            ctr_write();
            break;
        
        case USB_ENDPOINT_XFER_BULK:
            blk_write(ep_num);
            break;
        
        case USB_ENDPOINT_XFER_INT:
            int_write(ep_num);
            break;
    }
    
    if (block)
        /* wait for transfer to end */
        semaphore_wait(&ep->complete, TIMEOUT_BLOCK);

    return 0;
}
Exemple #19
0
Fichier : sys.c Projet : BFridge/OS
/**
 * This is the main system call function. It takes an interrupt stack frame
 * and decodes which interrupt number generated the system call. This number
 * is used to decode which system call was called.
 *
 * The stack frame is used to both pass and receive information from the
 * system call.
 * ECX: On completion of the system call ecx is populated with the return
 *      value
 * EAX: Contains the system call number
 * EBX: Contains the ptr to the first of the parameters
 *
 * @param frame Ptr to a handler_stack_frame struture
 * @return SUCCESS on success or FAILURE if something goes wrong
 */
int system_call( struct handler_stack_frame* frame )
{
    int system_call_number;
    char** system_call_params;
    int* system_call_result;

    system_call_result = (int*)frame->ecx;
    system_call_params = (char**)frame->ebx;
    system_call_number = frame->eax;

    switch( system_call_number )
    {
    case SYS_SEMA_CREATE:
        *system_call_result = semaphore_create( (sema_handle*)system_call_params[0], (int)system_call_params[1] );
        break;
    case SYS_SEMA_WAIT:
        *system_call_result = semaphore_wait( (int)system_call_params[0] );
        break;
    case SYS_SEMA_SIGNAL:
        *system_call_result = semaphore_signal( (int)system_call_params[0] );
        break;
    case SYS_SEMA_DESTROY:
        *system_call_result = semaphore_destroy( (int)system_call_params[0] );
        break;
    case SYS_THREAD_EXIT:
        *system_call_result = sys_thread_exit();
        break;
    case SYS_MSLEEP:
        *system_call_result = sys_msleep((uint)system_call_params[0] );
        break;
    default:
        *system_call_result = FAILURE;
        break;
    }

    return SUCCESS;
}
Exemple #20
0
/*
 * Block forever waiting for EVENT to be signalled,
 * or timeout after timeout (ms) have expired
 * set timeout to EMBX_TIMEOUT_INFINITE to wait forever
 *
 * Returns EMBX_SUCCESS if signalled, EMBX_SYSTEM_TIMEOUT otherwise
 */
EMBX_ERROR EMBX_OS_EventWaitTimeout(EMBX_EVENT ev, unsigned long timeout)
{
    int res;
    osclock_t time;

    EMBX_Assert(ev);

    if (timeout != EMBX_TIMEOUT_INFINITE)
    {
	/* OS21 semaphore timeout takes an absolute time value
	 * so we calculate that here
	 */
	time = time_plus(time_now(), (timeout*time_ticks_per_sec())/1000);
	res = semaphore_wait_timeout(ev->event, &time);
    }
    else
	/* Infinite wait */
	res = semaphore_wait(ev->event);

    if (res == OS21_FAILURE)
	return EMBX_SYSTEM_TIMEOUT;

    return EMBX_SUCCESS;
}
Exemple #21
0
int
printf(const char *fmt, ...)
{
	kern_return_t kern_res;
	va_list ap;
	if (!_init)
	{
		_init++;
		MACH_CALL(semaphore_create(mach_task_self(), 
					   &lock, 
					   SYNC_POLICY_FIFO,
					   1),
			  kern_res);
	}
	MACH_CALL(semaphore_wait(lock), kern_res);
	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
	MACH_CALL(semaphore_signal(lock), kern_res);
	if (kern_res == KERN_SUCCESS)
		return 0;
	else
		return -1;
}
void hotplug_task_fn(void *val)
{
  while(1)
  {
    semaphore_wait(hotplug_sem);
    switch(currentDisplayStatus)
    {
      case STM_DISPLAY_NEEDS_RESTART:
        if(!silent_hotplug) printf("HDMI TV Starting Link\n");
        if(stm_display_output_start(pHDMI, pModeLine, STM_OUTPUT_STD_CEA861C)<0)
        {
          if(!silent_hotplug) printf("Unable to start HDMI\n");
        }
        break;
      case STM_DISPLAY_CONNECTED:
        if(!silent_hotplug) printf("HDMI TV Successfully Connected\n");
        break;
      case STM_DISPLAY_DISCONNECTED:
        if(!silent_hotplug) printf("HDMI TV Disconnected\n");
        stm_display_output_stop(pHDMI);
        break;
    }
  }
}
/*!
 * @brief IO system initialization.
 *  When user wants to start up the codec system,
 *  this function call is needed, to open the codec device,
 *  map the register into user space,
 *  get the working buffer/code buffer/parameter buffer,
 *  download the firmware, and then set up the interrupt signal path.
 *
 * @param callback vpu interrupt callback.
 *
 * @return
 * @li  0	          System initialization success.
 * @li -1		System initialization failure.
 */
int IOSystemInit(void *callback)
{
	int ret;

	/* Exit directly if already initialized */
	if (vpu_fd > 0) {
		vpu_active_num++;
		return 0;
	}

	ret = get_system_rev();
	if (ret == -1) {
		err_msg("Error: Unable to obtain system rev information\n");
		return -1;
	}

	vpu_fd = open("/dev/mxc_vpu", O_RDWR);
	if (vpu_fd < 0) {
		err_msg("Can't open /dev/mxc_vpu: %s\n", strerror(errno));
		return -1;
	}

	vpu_shared_mem = vpu_semaphore_open();
	if (vpu_shared_mem == NULL) {
		err_msg("Error: Unable to open vpu shared memory file\n");
		close(vpu_fd);
		vpu_fd = -1;
		return -1;
	}

	if (!semaphore_wait(vpu_semap, API_MUTEX)) {
		err_msg("Error: Unable to get mutex\n");
		close (vpu_fd);
		vpu_fd = -1;
		return -1;
	}

	vpu_reg_base = (unsigned long)mmap(NULL, BIT_REG_MARGIN,
					   PROT_READ | PROT_WRITE,
					   MAP_SHARED, vpu_fd, 0);

	if ((void *)vpu_reg_base == MAP_FAILED) {
		err_msg("Can't map register\n");
		close(vpu_fd);
		vpu_fd = -1;
		semaphore_post(vpu_semap, API_MUTEX);
		return -1;
	}

	vpu_active_num++;

	IOClkGateSet(true);
#ifdef BUILD_FOR_ANDROID
	unsigned long va_addr;

	/* Special handle the bit work buffer, which reserved in vpu driver probe */
	bit_work_addr.size = TEMP_BUF_SIZE + PARA_BUF_SIZE +
			     CODE_BUF_SIZE + PARA_BUF2_SIZE;
	if (_IOGetPhyMem(VPU_IOC_GET_WORK_ADDR, &bit_work_addr) < 0) {
		err_msg("Get bitwork address failed!\n");
		goto err;
	}

	va_addr = (unsigned long)mmap(NULL, bit_work_addr.size, PROT_READ | PROT_WRITE,
					MAP_SHARED, vpu_fd, bit_work_addr.phy_addr);
	if ((void *)va_addr == MAP_FAILED) {
		bit_work_addr.virt_uaddr = 0;
		goto err;
	}

	bit_work_addr.virt_uaddr = va_addr;
#else
	bit_work_addr.size = TEMP_BUF_SIZE + PARA_BUF_SIZE +
			     CODE_BUF_SIZE + PARA_BUF2_SIZE;
	if (_IOGetPhyMem(VPU_IOC_GET_WORK_ADDR, &bit_work_addr) < 0) {
		err_msg("Get bitwork address failed!\n");
		goto err;
	}

	if (IOGetVirtMem(&bit_work_addr) == -1)
		goto err;
#endif
	UnlockVpu(vpu_semap);
	return 0;

      err:
	err_msg("Error in IOSystemInit()");
	UnlockVpu(vpu_semap);
	IOSystemShutdown();
	return -1;
}
Exemple #24
0
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
	ULONG Type;
	PVOID Object;

	if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
		return WAIT_FAILED;

	if (Type == HANDLE_TYPE_THREAD)
	{
		int status;
		WINPR_THREAD* thread;
		void* thread_status = NULL;

		if (dwMilliseconds != INFINITE)
			printf("WaitForSingleObject: timeout not implemented for thread wait\n");

		thread = (WINPR_THREAD*) Object;

		status = pthread_join(thread->thread, &thread_status);

		if (status != 0)
			printf("WaitForSingleObject: pthread_join failure: %d\n", status);
	}
	else if (Type == HANDLE_TYPE_MUTEX)
	{
		if (dwMilliseconds != INFINITE)
			printf("WaitForSingleObject: timeout not implemented for mutex wait\n");

		pthread_mutex_lock((pthread_mutex_t*) Object);
	}
	else if (Type == HANDLE_TYPE_EVENT)
	{
		int status;
		fd_set rfds;
		WINPR_EVENT* event;
		struct timeval timeout;

		event = (WINPR_EVENT*) Object;

		FD_ZERO(&rfds);
		FD_SET(event->pipe_fd[0], &rfds);
		ZeroMemory(&timeout, sizeof(timeout));

		if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
		{
			timeout.tv_usec = dwMilliseconds * 1000;
		}

		status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
				(dwMilliseconds == INFINITE) ? NULL : &timeout);

		if (status < 0)
			return WAIT_FAILED;

		if (status != 1)
			return WAIT_TIMEOUT;
	}
	else if (Type == HANDLE_TYPE_SEMAPHORE)
	{
		WINPR_SEMAPHORE* semaphore;

		semaphore = (WINPR_SEMAPHORE*) Object;

#ifdef WINPR_PIPE_SEMAPHORE
		if (semaphore->pipe_fd[0] != -1)
		{
			int status;
			int length;
			fd_set rfds;
			struct timeval timeout;

			FD_ZERO(&rfds);
			FD_SET(semaphore->pipe_fd[0], &rfds);
			ZeroMemory(&timeout, sizeof(timeout));

			if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
			{
				timeout.tv_usec = dwMilliseconds * 1000;
			}

			status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
					(dwMilliseconds == INFINITE) ? NULL : &timeout);

			if (status < 0)
				return WAIT_FAILED;

			if (status != 1)
				return WAIT_TIMEOUT;

			length = read(semaphore->pipe_fd[0], &length, 1);

			if (length != 1)
				return FALSE;
		}
#else

#if defined __APPLE__
		semaphore_wait(*((winpr_sem_t*) semaphore->sem));
#else
		sem_wait((winpr_sem_t*) semaphore->sem);
#endif

#endif
	}
	else
	{
		printf("WaitForSingleObject: unknown handle type %d\n", Type);
	}

	return WAIT_OBJECT_0;
}
Exemple #25
0
int main(int argc, char **argv) {
	int i, port, pid, listenfd, socketfd, hit, consumers;
	socklen_t length;
	static struct sockaddr_in cli_addr; /* static = initialised to zeros */
	static struct sockaddr_in serv_addr; /* static = initialised to zeros */

#if OperationMode == 2
	if (argc < 5 || argc > 5 || !strcmp(argv[1], "-?")) {
		printf("\n\nhint: ./tftps Port-Number Top-Directory Consumer-Threads Buffer-Size\n\n""\ttftps is a small and very safe mini ftp server\n""\tExample: ./tftps 8181 ./fileDir \n\n");
		exit(0);
	}
	consumers = atoi(argv[3]);

	initConsumerStruct(&shared, (size_t) atoi(argv[4]));
#else
	if (argc < 3 || argc > 3 || !strcmp(argv[1], "-?")) {
		printf("\n\nhint: ./tftps Port-Number Top-Directory\n\n""\ttftps is a small and very safe mini ftp server\n""\tExample: ./tftps 8181 ./fileDir \n\n");
		exit(0);
	}
#endif
	port = atoi(argv[1]);
	defaultPath = argv[2];

	if (chdir(defaultPath) == -1) {
		printf("ERROR: Can't Change to directory %s\n", argv[2]);
		exit(4);
	}

	printf("LOG tftps starting %s - pid %d\n", argv[1], getpid());

	/* setup the network socket */
	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("ERROR system call - setup the socket\n");
	if (port < 0 || port > 60000)
		printf("ERROR Invalid port number (try 1->60000)\n");

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(port);

	if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		printf("ERROR system call - bind error\n");
	if (listen(listenfd, 64) < 0)
		printf("ERROR system call - listen error\n");

#if OperationMode == 2
	pthread_t idC;
	int index = 0, item;

#if ApplePositive
    semaphore_create(mach_task_self(), &shared.full, SYNC_POLICY_FIFO, 0);
    semaphore_create(mach_task_self(), &shared.empty, SYNC_POLICY_FIFO, shared.buffSize);
#else
	sem_t *semFull = sem_open("/semFull", O_CREAT, 0644, 0);
	sem_t *semEmpty = sem_open("/semEmpty", O_CREAT, 0644, shared.buffSize);

	shared.full = *semFull;
	shared.empty = *semEmpty;
#endif

	pthread_mutex_init(&shared.mutex, NULL);

	/*create a new Consumer*/
	for(index=0; index<consumers; index++)
	{
		pthread_create(&idC, NULL, Consumer, (void*)&index);
	}

	struct sigaction act;
	act.sa_handler = &onAlarm;
	act.sa_flags = SA_RESTART;  // Restart interrupted system calls
	sigaction(SIGALRM, &act, NULL);

	alarm(30);
#endif

	// Main LOOP
	for (hit = 1 ;; hit++) {
		length = sizeof(cli_addr);

		/* block waiting for clients */
		socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);
		if (socketfd < 0)
			printf("ERROR system call - accept error\n");
		else
		{
#if OperationMode
#if OperationMode == 1
			pthread_t thread_id;

			THREAD_ARGS *args = malloc(sizeof(THREAD_ARGS));

			int * sockAUX = (int *) malloc(sizeof(int *));

			*sockAUX = socketfd;

			args->fd = sockAUX;
			args->hit = hit;

			if (args != NULL) {
				if (pthread_create(&thread_id, NULL, &attendFTP, args)) {
					perror("could not create thread");
					return 1;
				}
			}
#else
			item = socketfd;

#if ApplePositive
            semaphore_wait(shared.empty);
#else
			sem_wait(&shared.empty);
#endif
            pthread_mutex_lock(&shared.mutex);

			shared.buff[shared.in] = item;

			pthread_mutex_unlock(&shared.mutex);

			shared.in = (shared.in + 1) % shared.buffSize;

#if ApplePositive
			semaphore_signal(shared.full);
#else
			sem_post(&shared.full);
#endif
#endif
#else
			pid = fork();
                if(pid==0) {
                    ftp(socketfd, hit);
                    exit(0);
                } else {
                    //Temos de fechar o socketfd para que seja apenas a child a tratar dos pedidos, caso contrário iria ficar aqui pendurado
                    close(socketfd);
                    signal(pid, SIGCHLD);
                }
#endif
		}
	}
}
/**
 * Placed at the head of all monitor functions, this enters a monitor
 * or waits if it is occupied.
 */
void monitor_enter(monitor_t *monitor) {
  semaphore_wait(monitor->sem_id, MUTEX_SEM);
}
Exemple #27
0
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
	ULONG Type;
	PVOID Object;

	if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
	{
		fprintf(stderr, "WaitForSingleObject failed: invalid hHandle.\n");
		return WAIT_FAILED;
	}

	if (Type == HANDLE_TYPE_THREAD)
	{
		int status = 0;
		WINPR_THREAD* thread;
		void* thread_status = NULL;

		thread = (WINPR_THREAD*) Object;

		if (thread->started)
		{
			if (dwMilliseconds != INFINITE)
			{
				struct timespec timeout;

				/* pthread_timedjoin_np returns ETIMEDOUT in case the timeout is 0,
				 * so set it to the smallest value to get a proper return value. */
				if (dwMilliseconds == 0)
					dwMilliseconds ++;

				clock_gettime(CLOCK_MONOTONIC, &timeout);
				ts_add_ms(&timeout, dwMilliseconds);

				status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);

				if (ETIMEDOUT == status)
					return WAIT_TIMEOUT;
			}
			else
				status = pthread_join(thread->thread, &thread_status);

			if (status != 0)
			{
				fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n",
						status, strerror(status));
			}

			if (thread_status)
				thread->dwExitCode = ((DWORD) (size_t) thread_status);
		}
	}
	else if (Type == HANDLE_TYPE_PROCESS)
	{
		WINPR_PROCESS* process;

		process = (WINPR_PROCESS*) Object;

		if (waitpid(process->pid, &(process->status), 0) != -1)
		{
			fprintf(stderr, "WaitForSingleObject: waitpid failure [%d] %s\n", errno, strerror(errno));
			return WAIT_FAILED;
		}

		process->dwExitCode = (DWORD) process->status;
	}
	else if (Type == HANDLE_TYPE_MUTEX)
	{
		WINPR_MUTEX* mutex;

		mutex = (WINPR_MUTEX*) Object;

		if (dwMilliseconds != INFINITE)
		{
			int status;
			struct timespec timeout;

			clock_gettime(CLOCK_MONOTONIC, &timeout);
			ts_add_ms(&timeout, dwMilliseconds);	

			status = pthread_mutex_timedlock(&mutex->mutex, &timeout);

			if (ETIMEDOUT == status)
				return WAIT_TIMEOUT;
		}
		else
		{
			pthread_mutex_lock(&mutex->mutex);
		}
	}
	else if (Type == HANDLE_TYPE_EVENT)
	{
		int status;
		fd_set rfds;
		WINPR_EVENT* event;
		struct timeval timeout;

		event = (WINPR_EVENT*) Object;

		FD_ZERO(&rfds);
		FD_SET(event->pipe_fd[0], &rfds);
		ZeroMemory(&timeout, sizeof(timeout));

		if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
		{
			timeout.tv_sec = dwMilliseconds / 1000;
			timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
		}

		do
		{
			status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
					(dwMilliseconds == INFINITE) ? NULL : &timeout);
		}
		while (status < 0 && (errno == EINTR));

		if (status < 0)
		{
			fprintf(stderr, "WaitForSingleObject: event select() failure [%d] %s\n", errno, strerror(errno));
			return WAIT_FAILED;
		}

		if (status != 1)
			return WAIT_TIMEOUT;
	}
	else if (Type == HANDLE_TYPE_SEMAPHORE)
	{
		WINPR_SEMAPHORE* semaphore;

		semaphore = (WINPR_SEMAPHORE*) Object;

#ifdef WINPR_PIPE_SEMAPHORE
		if (semaphore->pipe_fd[0] != -1)
		{
			int status;
			int length;
			fd_set rfds;
			struct timeval timeout;

			FD_ZERO(&rfds);
			FD_SET(semaphore->pipe_fd[0], &rfds);
			ZeroMemory(&timeout, sizeof(timeout));

			if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
			{
				timeout.tv_sec = dwMilliseconds / 1000;
				timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
			}

			do
			{
				status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
						(dwMilliseconds == INFINITE) ? NULL : &timeout);
			}
			while (status < 0 && (errno == EINTR));

			if (status < 0)
			{
				fprintf(stderr, "WaitForSingleObject: semaphore select() failure [%d] %s\n", errno, strerror(errno));
				return WAIT_FAILED;
			}

			if (status != 1)
				return WAIT_TIMEOUT;

			length = read(semaphore->pipe_fd[0], &length, 1);

			if (length != 1)
			{
				fprintf(stderr, "WaitForSingleObject: semaphore read failure [%d] %s\n", errno, strerror(errno));
				return WAIT_FAILED;
			}
		}
#else

#if defined __APPLE__
		semaphore_wait(*((winpr_sem_t*) semaphore->sem));
#else
		sem_wait((winpr_sem_t*) semaphore->sem);
#endif

#endif
	}
	else if (Type == HANDLE_TYPE_TIMER)
	{
		WINPR_TIMER* timer;

		timer = (WINPR_TIMER*) Object;

#ifdef HAVE_EVENTFD_H
		if (timer->fd != -1)
		{
			int status;
			fd_set rfds;
			UINT64 expirations;
			struct timeval timeout;

			FD_ZERO(&rfds);
			FD_SET(timer->fd, &rfds);
			ZeroMemory(&timeout, sizeof(timeout));

			if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
			{
				timeout.tv_sec = dwMilliseconds / 1000;
				timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
			}

			do
			{
				status = select(timer->fd + 1, &rfds, 0, 0,
						(dwMilliseconds == INFINITE) ? NULL : &timeout);
			}
			while (status < 0 && (errno == EINTR));

			if (status < 0)
			{
				fprintf(stderr, "WaitForSingleObject: timer select() failure [%d] %s\n", errno, strerror(errno));
				return WAIT_FAILED;
			}

			if (status != 1)
				return WAIT_TIMEOUT;

			status = read(timer->fd, (void*) &expirations, sizeof(UINT64));

			if (status != 8)
			{
				if (status == -1)
				{
					if (errno == ETIMEDOUT)
						return WAIT_TIMEOUT;

					fprintf(stderr, "WaitForSingleObject: timer read() failure [%d] %s\n", errno, strerror(errno));
				}
				else
				{
					fprintf(stderr, "WaitForSingleObject: timer read() failure - incorrect number of bytes read");
				}

				return WAIT_FAILED;
			}
		}
		else
		{
			fprintf(stderr, "WaitForSingleObject: invalid timer file descriptor\n");
			return WAIT_FAILED;
		}

#else
		fprintf(stderr, "WaitForSingleObject: file descriptors not supported\n");
		return WAIT_FAILED;
#endif
	}
	else if (Type == HANDLE_TYPE_NAMED_PIPE)
	{
		int fd;
		int status;
		fd_set rfds;
		struct timeval timeout;
		WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object;

		fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd;

		if (fd == -1)
		{
			fprintf(stderr, "WaitForSingleObject: invalid pipe file descriptor\n");
			return WAIT_FAILED;
		}

		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);
		ZeroMemory(&timeout, sizeof(timeout));

		if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
		{
			timeout.tv_sec = dwMilliseconds / 1000;
			timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
		}

		do
		{
			status = select(fd + 1, &rfds, NULL, NULL,
					(dwMilliseconds == INFINITE) ? NULL : &timeout);
		}
		while (status < 0 && (errno == EINTR));

		if (status < 0)
		{
			fprintf(stderr, "WaitForSingleObject: named pipe select() failure [%d] %s\n", errno, strerror(errno));
			return WAIT_FAILED;
		}

		if (status != 1)
		{
			return WAIT_TIMEOUT;
		}
	}
	else
	{
		fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type);
	}

	return WAIT_OBJECT_0;
}
void pthread_hijack(Addr self, Addr kport, Addr func, Addr func_arg, 
                    Addr stacksize, Addr flags, Addr sp)
{
   vki_sigset_t blockall;
   ThreadState *tst = (ThreadState *)func_arg;
   VexGuestAMD64State *vex = &tst->arch.vex;

   // VG_(printf)("pthread_hijack pthread %p, machthread %p, func %p, arg %p, stack %p, flags %p, stack %p\n", self, kport, func, func_arg, stacksize, flags, sp);

   // Wait for parent thread's permission.
   // The parent thread holds V's lock on our behalf.
   semaphore_wait(tst->os_state.child_go);

   /* Start the thread with all signals blocked.  VG_(scheduler) will
      set the mask correctly when we finally get there. */
   VG_(sigfillset)(&blockall);
   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, NULL);

   // Set thread's registers
   // Do this FIRST because some code below tries to collect a backtrace, 
   // which requires valid register data.
   LibVEX_GuestAMD64_initialise(vex);
   vex->guest_RIP = pthread_starter;
   vex->guest_RDI = self;
   vex->guest_RSI = kport;
   vex->guest_RDX = func;
   vex->guest_RCX = tst->os_state.func_arg;
   vex->guest_R8  = stacksize;
   vex->guest_R9  = flags;
   vex->guest_RSP = sp;

   // Record thread's stack and Mach port and pthread struct
   tst->os_state.pthread = self;
   tst->os_state.lwpid = kport;
   record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "thread-%p");

   if ((flags & 0x01000000) == 0) {
      // kernel allocated stack - needs mapping
      Addr stack = VG_PGROUNDUP(sp) - stacksize;
      tst->client_stack_highest_word = stack+stacksize;
      tst->client_stack_szB = stacksize;

      // pthread structure
      ML_(notify_core_and_tool_of_mmap)(
            stack+stacksize, pthread_structsize, 
            VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0);
      // stack contents
      ML_(notify_core_and_tool_of_mmap)(
            stack, stacksize, 
            VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0);
      // guard page
      ML_(notify_core_and_tool_of_mmap)(
            stack-VKI_PAGE_SIZE, VKI_PAGE_SIZE,
            0, VKI_MAP_PRIVATE, -1, 0);
   } else {
      // client allocated stack
      find_stack_segment(tst->tid, sp);
   }
   ML_(sync_mappings)("after", "pthread_hijack", 0);

   // DDD: should this be here rather than in POST(sys_bsdthread_create)?
   // But we don't have ptid here...
   //VG_TRACK ( pre_thread_ll_create, ptid, tst->tid );

   // Tell parent thread's POST(sys_bsdthread_create) that we're done 
   // initializing registers and mapping memory.
   semaphore_signal(tst->os_state.child_done);
   // LOCK IS GONE BELOW THIS POINT

   // Go!
   call_on_new_stack_0_1(tst->os_state.valgrind_stack_init_SP, 0, 
                         start_thread_NORETURN, (Word)tst);

   /*NOTREACHED*/
   vg_assert(0);
}
Exemple #29
0
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
	ULONG Type;
	PVOID Object;

	if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
		return WAIT_FAILED;

	if (Type == HANDLE_TYPE_THREAD)
	{
		int status = 0;
		WINPR_THREAD* thread;
		void* thread_status = NULL;

		thread = (WINPR_THREAD*) Object;

		if (thread->started)
		{
			if (dwMilliseconds != INFINITE)
			{
#if HAVE_PTHREAD_GNU_EXT
				struct timespec timeout;

				clock_gettime(CLOCK_REALTIME, &timeout);
				ts_add_ms(&timeout, dwMilliseconds);

				status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);
#else
				fprintf(stderr, "[ERROR] %s: Thread timeouts not implemented.\n", __func__);
				assert(0);
#endif
			}
			else
				status = pthread_join(thread->thread, &thread_status);

			if (status != 0)
				fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n",
						status, strerror(status));

			if (thread_status)
				thread->dwExitCode = ((DWORD) (size_t) thread_status);
		}
	}
	else if (Type == HANDLE_TYPE_MUTEX)
	{
		WINPR_MUTEX* mutex;

		mutex = (WINPR_MUTEX*) Object;

#if HAVE_PTHREAD_GNU_EXT
		if (dwMilliseconds != INFINITE)
		{
			struct timespec timeout;

			clock_gettime(CLOCK_REALTIME, &timeout);
			ts_add_ms(&timeout, dwMilliseconds);	

			pthread_mutex_timedlock(&mutex->mutex, &timeout);
		}
		else
#endif
		{
			pthread_mutex_lock(&mutex->mutex);
		}
	}
	else if (Type == HANDLE_TYPE_EVENT)
	{
		int status;
		fd_set rfds;
		WINPR_EVENT* event;
		struct timeval timeout;

		event = (WINPR_EVENT*) Object;

		FD_ZERO(&rfds);
		FD_SET(event->pipe_fd[0], &rfds);
		ZeroMemory(&timeout, sizeof(timeout));

		if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
		{
			timeout.tv_usec = dwMilliseconds * 1000;
		}

		status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
				(dwMilliseconds == INFINITE) ? NULL : &timeout);

		if (status < 0)
			return WAIT_FAILED;

		if (status != 1)
			return WAIT_TIMEOUT;
	}
	else if (Type == HANDLE_TYPE_SEMAPHORE)
	{
		WINPR_SEMAPHORE* semaphore;

		semaphore = (WINPR_SEMAPHORE*) Object;

#ifdef WINPR_PIPE_SEMAPHORE
		if (semaphore->pipe_fd[0] != -1)
		{
			int status;
			int length;
			fd_set rfds;
			struct timeval timeout;

			FD_ZERO(&rfds);
			FD_SET(semaphore->pipe_fd[0], &rfds);
			ZeroMemory(&timeout, sizeof(timeout));

			if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
			{
				timeout.tv_usec = dwMilliseconds * 1000;
			}

			status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
					(dwMilliseconds == INFINITE) ? NULL : &timeout);

			if (status < 0)
				return WAIT_FAILED;

			if (status != 1)
				return WAIT_TIMEOUT;

			length = read(semaphore->pipe_fd[0], &length, 1);

			if (length != 1)
				return WAIT_FAILED;
		}
#else

#if defined __APPLE__
		semaphore_wait(*((winpr_sem_t*) semaphore->sem));
#else
		sem_wait((winpr_sem_t*) semaphore->sem);
#endif

#endif
	}
	else if (Type == HANDLE_TYPE_TIMER)
	{
		WINPR_TIMER* timer;

		timer = (WINPR_TIMER*) Object;

#ifdef HAVE_EVENTFD_H
		if (timer->fd != -1)
		{
			int status;
			fd_set rfds;
			UINT64 expirations;
			struct timeval timeout;

			FD_ZERO(&rfds);
			FD_SET(timer->fd, &rfds);
			ZeroMemory(&timeout, sizeof(timeout));

			if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
			{
				timeout.tv_usec = dwMilliseconds * 1000;
			}

			status = select(timer->fd + 1, &rfds, 0, 0,
					(dwMilliseconds == INFINITE) ? NULL : &timeout);

			if (status < 0)
				return WAIT_FAILED;

			if (status != 1)
				return WAIT_TIMEOUT;

			status = read(timer->fd, (void*) &expirations, sizeof(UINT64));

			if (status != 8)
				return WAIT_TIMEOUT;
		}
		else
		{
			return WAIT_FAILED;
		}
#else
		return WAIT_FAILED;
#endif
	}
	else if (Type == HANDLE_TYPE_NAMED_PIPE)
	{
		int status;
		fd_set rfds;
		struct timeval timeout;
		WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object;

		FD_ZERO(&rfds);
		FD_SET(pipe->clientfd, &rfds);
		ZeroMemory(&timeout, sizeof(timeout));

		if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
		{
			timeout.tv_usec = dwMilliseconds * 1000;
		}

		status = select(pipe->clientfd + 1, &rfds, NULL, NULL,
				(dwMilliseconds == INFINITE) ? NULL : &timeout);

		if (status < 0)
			return WAIT_FAILED;

		if (status != 1)
			return WAIT_TIMEOUT;
	}
	else
	{
		fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type);
	}

	return WAIT_OBJECT_0;
}
Exemple #30
0
DISPATCH_NOINLINE
static long
_dispatch_group_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout)
{
	long orig;

again:
	// check before we cause another signal to be sent by incrementing
	// dsema->dsema_group_waiters
	if (dsema->dsema_value == dsema->dsema_orig) {
		return _dispatch_group_wake(dsema);
	}
	// Mach semaphores appear to sometimes spuriously wake up. Therefore,
	// we keep a parallel count of the number of times a Mach semaphore is
	// signaled (6880961).
	(void)dispatch_atomic_inc2o(dsema, dsema_group_waiters);
	// check the values again in case we need to wake any threads
	if (dsema->dsema_value == dsema->dsema_orig) {
		return _dispatch_group_wake(dsema);
	}

#if USE_MACH_SEM
	mach_timespec_t _timeout;
	kern_return_t kr;

	_dispatch_semaphore_create_port(&dsema->dsema_waiter_port);

	// From xnu/osfmk/kern/sync_sema.c:
	// wait_semaphore->count = -1; /* we don't keep an actual count */
	//
	// The code above does not match the documentation, and that fact is
	// not surprising. The documented semantics are clumsy to use in any
	// practical way. The above hack effectively tricks the rest of the
	// Mach semaphore logic to behave like the libdispatch algorithm.

	switch (timeout) {
	default:
		do {
			uint64_t nsec = _dispatch_timeout(timeout);
			_timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC);
			_timeout.tv_nsec = (typeof(_timeout.tv_nsec))(nsec % NSEC_PER_SEC);
			kr = slowpath(semaphore_timedwait(dsema->dsema_waiter_port,
					_timeout));
		} while (kr == KERN_ABORTED);

		if (kr != KERN_OPERATION_TIMED_OUT) {
			DISPATCH_SEMAPHORE_VERIFY_KR(kr);
			break;
		}
		// Fall through and try to undo the earlier change to
		// dsema->dsema_group_waiters
	case DISPATCH_TIME_NOW:
		while ((orig = dsema->dsema_group_waiters)) {
			if (dispatch_atomic_cmpxchg2o(dsema, dsema_group_waiters, orig,
					orig - 1)) {
				return KERN_OPERATION_TIMED_OUT;
			}
		}
		// Another thread called semaphore_signal().
		// Fall through and drain the wakeup.
	case DISPATCH_TIME_FOREVER:
		do {
			kr = semaphore_wait(dsema->dsema_waiter_port);
		} while (kr == KERN_ABORTED);
		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
		break;
	}
#elif USE_POSIX_SEM
	struct timespec _timeout;
	int ret;

	switch (timeout) {
	default:
		do {
			_timeout = _dispatch_timeout_ts(timeout);
			ret = slowpath(sem_timedwait(&dsema->dsema_sem, &_timeout));
		} while (ret == -1 && errno == EINTR);

		if (!(ret == -1 && errno == ETIMEDOUT)) {
			DISPATCH_SEMAPHORE_VERIFY_RET(ret);
			break;
		}
		// Fall through and try to undo the earlier change to
		// dsema->dsema_group_waiters
	case DISPATCH_TIME_NOW:
		while ((orig = dsema->dsema_group_waiters)) {
			if (dispatch_atomic_cmpxchg2o(dsema, dsema_group_waiters, orig,
					orig - 1)) {
				errno = ETIMEDOUT;
				return -1;
			}
		}
		// Another thread called semaphore_signal().
		// Fall through and drain the wakeup.
	case DISPATCH_TIME_FOREVER:
		do {
			ret = sem_wait(&dsema->dsema_sem);
		} while (ret == -1 && errno == EINTR);
		DISPATCH_SEMAPHORE_VERIFY_RET(ret);
		break;
	}
#endif

	goto again;
}