Beispiel #1
0
int
main(void)
{
    pthread_t     pthread1, pthread2, pthread3;
    semaphore_t*   sem = g_sem;
    kern_return_t kr;

    setbuf(stdout, NULL);

    kr = semaphore_create(mach_task_self(), &sem[0], SYNC_POLICY_FIFO, 0);
    OUT_ON_MACH_ERROR("semaphore_create", kr);

    kr = semaphore_create(mach_task_self(), &sem[1], SYNC_POLICY_FIFO, 0);
    OUT_ON_MACH_ERROR("semaphore_create", kr);

    (void)pthread_create(&pthread1, (const pthread_attr_t *)0,
                         start_routine, (void *) 0);
    printf("created thread1=%lx\n", 0);

    (void)pthread_create(&pthread2, (const pthread_attr_t *)0,
                         start_routine, (void *) 1);
    printf("created thread2=%lx\n", 1);

    (void)pthread_create(&pthread3, (const pthread_attr_t *)0,
                         start_routine, (void *) 2);
    printf("created thread3=%lx\n", 2);

    // wait until all three threads are ready
    SEMAPHORE_WAIT(sem[1], 3);

//    printf("main: about to signal thread3\n");
//    semaphore_signal_thread(sem[0], pthread_mach_thread_np(pthread3));

    // wait for thread3 to sem_signal()
//    semaphore_wait(sem[1]);

    sleep(1);
    printf("main: about to signal all threads\n");
    semaphore_signal_all(sem[0]);

    // wait for thread1 and thread2 to sem_signal()
    SEMAPHORE_WAIT(sem[1], 3);

out:
    if (sem[0])
        semaphore_destroy(mach_task_self(), sem[0]);
    if (sem[1])
        semaphore_destroy(mach_task_self(), sem[1]);

    exit(kr);
}
Beispiel #2
0
int
semaphore_release(semaphore_t semaphore)
{
    int result = 0;
    proc_t notify = NULL;
    int irq = __irq_save();
    spinlock_acquire(&semaphore->lock);
    if (SEMAPHORE_WAIT(semaphore))
    {
        ips_node_t node = SEMAPHORE_PTR(semaphore);
        IPS_NODE_WAIT_CLEAR(node);

        notify = IPS_NODE_PTR(node);

        node->next->prev = node->prev;
        node->prev->next = node->next;
        if (node->next == node)
            SEMAPHORE_WAIT_CLEAR(semaphore);
        else SEMAPHORE_PTR_SET(semaphore, node->next);

        result = 1;
    }
    else
    {
        ++ semaphore->count;
    }
    spinlock_release(&semaphore->lock);
    __irq_restore(irq);

    if (notify != NULL)
        proc_notify(notify);

    return result;
}
Beispiel #3
0
uintptr_t
semaphore_acquire(semaphore_t semaphore, ips_node_t node)
{
    uintptr_t result;
    if (node == NULL)
    {
        ips_node_s node;
        result = semaphore_acquire(semaphore, &node);
        if (!result)
            ips_wait(&node);

        return result;
    }
    else
    {
        int irq = __irq_save();
        spinlock_acquire(&semaphore->lock);
        result = semaphore->count;
        if (result > 0)
        {
            if (-- semaphore->count == 0)
                SEMAPHORE_WAIT_CLEAR(semaphore);
          
            spinlock_release(&semaphore->lock);
            __irq_restore(irq);
               
            IPS_NODE_WAIT_CLEAR(node);
          
            return result;
        }
        else
        {
            ips_wait_init(node, current);

            if (SEMAPHORE_WAIT(semaphore))
            {
                node->next = SEMAPHORE_PTR(semaphore);
                node->prev = node->next->prev;
                node->next->prev = node;
                node->prev->next = node;
            }
            else
            {
                SEMAPHORE_WAIT_SET(semaphore);
                node->next = node->prev = node;
                SEMAPHORE_PTR_SET(semaphore, node);
            }

            spinlock_release(&semaphore->lock);
            __irq_restore(irq);
               
            return result;
        }         
    }
}
Beispiel #4
0
/* can be called from any thread */
static uint32 VCHAN_CC
MyVirtualChannelWrite(uint32 openHandle, void * pData, uint32 dataLength,
	void * pUserData)
{
	rdpChanMan * chan_man;
	struct chan_data * lchan;
	int index;

	chan_man = freerdp_chanman_find_by_open_handle(openHandle, &index);
	if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT))
	{
		DEBUG_CHANMAN("MyVirtualChannelWrite: error bad chanhan");
		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
	}
	if (!chan_man->is_connected)
	{
		DEBUG_CHANMAN("MyVirtualChannelWrite: error not connected");
		return CHANNEL_RC_NOT_CONNECTED;
	}
	if (pData == 0)
	{
		DEBUG_CHANMAN("MyVirtualChannelWrite: error bad pData");
		return CHANNEL_RC_NULL_DATA;
	}
	if (dataLength == 0)
	{
		DEBUG_CHANMAN("MyVirtualChannelWrite: error bad dataLength");
		return CHANNEL_RC_ZERO_LENGTH;
	}
	lchan = chan_man->chans + index;
	if (lchan->flags != 2)
	{
		DEBUG_CHANMAN("MyVirtualChannelWrite: error not open");
		return CHANNEL_RC_NOT_OPEN;
	}
	SEMAPHORE_WAIT(chan_man->sem); /* lock chan_man->sync* vars */
	if (!chan_man->is_connected)
	{
		SEMAPHORE_POST(chan_man->sem);
		DEBUG_CHANMAN("MyVirtualChannelWrite: error not connected");
		return CHANNEL_RC_NOT_CONNECTED;
	}
	chan_man->sync_data = pData;
	chan_man->sync_data_length = dataLength;
	chan_man->sync_user_data = pUserData;
	chan_man->sync_index = index;
	/* set the event */
	freerdp_chanman_set_ev(chan_man);
	return CHANNEL_RC_OK;
}
Beispiel #5
0
static uint32 VCHAN_CC
MyVirtualChannelEventPush(uint32 openHandle,
	RD_EVENT * event)
{
	rdpChanMan * chan_man;
	struct chan_data * lchan;
	int index;

	chan_man = freerdp_chanman_find_by_open_handle(openHandle, &index);
	if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT))
	{
		DEBUG_CHANMAN("MyVirtualChannelEventPush: error bad chanhan");
		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
	}
	if (!chan_man->is_connected)
	{
		DEBUG_CHANMAN("MyVirtualChannelEventPush: error not connected");
		return CHANNEL_RC_NOT_CONNECTED;
	}
	if (event == NULL)
	{
		DEBUG_CHANMAN("MyVirtualChannelEventPush: error bad event");
		return CHANNEL_RC_NULL_DATA;
	}
	lchan = chan_man->chans + index;
	if (lchan->flags != 2)
	{
		DEBUG_CHANMAN("MyVirtualChannelEventPush: error not open");
		return CHANNEL_RC_NOT_OPEN;
	}
	SEMAPHORE_WAIT(chan_man->sem_event); /* lock chan_man->event */
	if (!chan_man->is_connected)
	{
		SEMAPHORE_POST(chan_man->sem_event);
		DEBUG_CHANMAN("MyVirtualChannelEventPush: error not connected");
		return CHANNEL_RC_NOT_CONNECTED;
	}
	chan_man->event = event;
	/* set the event */
	freerdp_chanman_set_ev(chan_man);
	return CHANNEL_RC_OK;
}