/*!
 * Block thread (on conditional variable) and release monitor
 */
int sys__monitor_wait ( monitor_t *monitor, monitor_q *queue )
{
	kmonitor_t *kmonitor;
	kmonitor_q *kqueue;

	ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE );
	ASSERT_ERRNO_AND_EXIT ( queue && queue->ptr, E_INVALID_HANDLE );

	kmonitor = monitor->ptr;
	kqueue = queue->ptr;

	ASSERT_ERRNO_AND_EXIT ( kmonitor->owner == k_get_active_thread (),
				E_NOT_OWNER );

	disable_interrupts ();

	SET_ERRNO ( SUCCESS );

	k_set_thread_qdata ( NULL, kmonitor );
	k_enqueue_thread ( NULL, &kqueue->queue );

	kmonitor->owner = k_threadq_get ( &kmonitor->queue );
	if ( !k_release_thread ( &kmonitor->queue ) )
		kmonitor->lock = FALSE;

	k_schedule_threads ();

	enable_interrupts ();

	EXIT ( SUCCESS );
}
/*!
 * Unlock monitor (or block trying)
 */
int sys__monitor_unlock ( monitor_t *monitor )
{
	kmonitor_t *kmonitor;

	ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE );

	kmonitor = monitor->ptr;

	ASSERT_ERRNO_AND_EXIT ( kmonitor->owner == k_get_active_thread (),
				E_NOT_OWNER );

	disable_interrupts ();

	SET_ERRNO ( SUCCESS );

	kmonitor->owner = k_threadq_get ( &kmonitor->queue );
	if ( !k_release_thread ( &kmonitor->queue ) )
		kmonitor->lock = FALSE;
	else
		k_schedule_threads ();

	enable_interrupts ();

	EXIT ( SUCCESS );
}
/*! Unlock device */
int k_device_unlock ( kdevice_t *dev )
{
	if ( k_release_thread ( &dev->thrq ) )
		k_schedule_threads ();
	else
		dev->locked = FALSE;

	return 0;
}
/*! Release first or all threads from monitor queue (cond.var.) */
static int k_monitor_release ( monitor_q *queue, int broadcast )
{
	kmonitor_q *kqueue;
	kthread_t *kthr;
	kmonitor_t *kmonitor;
	int reschedule = 0;

	ASSERT_ERRNO_AND_EXIT ( queue && queue->ptr, E_INVALID_HANDLE );

	disable_interrupts ();

	kqueue = queue->ptr;

	do {
		kthr = k_threadq_get ( &kqueue->queue ); /* first from queue */

		if ( !kthr )
			break;

		kmonitor = k_get_thread_qdata ( kthr );

		if ( !kmonitor->lock ) /* monitor not locked? */
		{
			/* unblocked thread becomes monitor owner */
			kmonitor->lock = TRUE;
			kmonitor->owner = kthr;
			k_release_thread ( &kqueue->queue );/*to ready threads*/
			reschedule++;
		}
		else {
			/* move thread from monitor queue (cond.var.)
			   to monitor entrance queue */
			kthr = k_threadq_remove ( &kqueue->queue, NULL );
			k_enqueue_thread ( kthr, &kmonitor->queue );
		}
	}
	while ( kthr && broadcast );

	SET_ERRNO ( SUCCESS );

	if ( reschedule )
		k_schedule_threads ();

	enable_interrupts ();

	EXIT ( SUCCESS );
}
/*!
 * Send message to queue or signal to thread
 */
int sys__msg_post ( void *p )
{
	/* parameters on thread stack */
	int dest_type;	/* MSG_QUEUE, MSG_THREAD or MSG_SIGNAL	*/
	void *dest;	/* (msg_q *) or (thread_t *)		*/
	msg_t *msg;	/* { type, size, data[0..size-1] }	*/
	uint flags;
	/* local variables */
	thread_t *thr;
	kthread_t *kthr, *new_kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;
	msg_t *cmsg;
	kprocess_t *proc;

	dest_type = *( (int *) p );	p += sizeof (int);
	dest = *( (void **) p );	p += sizeof (void *);
	msg = *( (msg_t **) p );	p += sizeof (msg_t *);
	flags = *( (uint *) p );

	ASSERT_ERRNO_AND_EXIT ( dest && msg, E_INVALID_HANDLE );

	dest = U2K_GET_ADR ( dest, k_get_active_process () );
	msg = U2K_GET_ADR ( msg, k_get_active_process () );

	if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL )
	{
		thr = dest;
		kthr = k_get_kthread ( thr );
		ASSERT_ERRNO_AND_EXIT ( kthr, E_DONT_EXIST );
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else if ( dest_type == MSG_QUEUE )
	{
		msgq = dest;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}
	else {
		EXIT ( E_INVALID_TYPE );
	}

	if ( dest_type == MSG_THREAD || dest_type == MSG_QUEUE )
	{
		/* send message to queue */
		if ( kmsgq->min_prio <= msg->type ) /* msg has required prio. */
		{
			kmsg = kmalloc ( sizeof (kmsg_t) + msg->size );
			ASSERT_ERRNO_AND_EXIT ( kmsg, E_NO_MEMORY );

			kmsg->msg.type = msg->type;
			kmsg->msg.size = msg->size;
			memcpy ( kmsg->msg.data, msg->data, msg->size );

			list_append ( &kmsgq->msgs, kmsg, &kmsg->list );

			/* is thread waiting for message? */
			if ( k_release_thread ( &kmsgq->thrq ) )
				k_schedule_threads ();

			EXIT ( SUCCESS );
		}
		else { /* ignore message */
			EXIT ( E_IGNORED );
		}
	}

	/* must be MSG_SIGNAL */
	if ( thrmsg->sig_prio <= msg->type )
	{
		/* create thread that will service this signal */

		cmsg = k_create_thread_private_storage ( kthr,
				sizeof (msg_t) + msg->size );
		cmsg->type = msg->type;
		cmsg->size = msg->size;
		memcpy ( cmsg->data, msg->data, msg->size );

		proc = k_get_thread_process ( kthr );

		new_kthr = k_create_thread (
			thrmsg->signal_handler,
			K2U_GET_ADR ( cmsg, proc ), proc->pi->exit,
			k_get_thread_prio ( kthr ) + 1, NULL, 0, 1, proc
		);
		ASSERT_ERRNO_AND_EXIT ( new_kthr, k_get_errno() );

		k_set_thread_private_storage ( new_kthr, cmsg );

		SET_ERRNO ( SUCCESS );

		k_schedule_threads ();

		RETURN ( SUCCESS );
	}
	else { /* ignore signal */
		EXIT ( E_IGNORED );
	}
}
Example #6
0
/*! Send message to queue or signal to thread */
int sys__msg_post ( int dest_type, void *dest, msg_t *msg, uint flags )
{
    thread_t *thr;
    kthread_t *kthr, *new_kthr;
    kthrmsg_qs *thrmsg;
    kgmsg_q *kgmsgq;
    kmsg_q *kmsgq;
    msg_q *msgq;
    kmsg_t *kmsg;
    msg_t *cmsg;

    SYS_ENTRY();

    ASSERT_ERRNO_AND_SYS_EXIT ( dest && msg, E_INVALID_HANDLE );

    if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL )
    {
        thr = dest;
        kthr = k_get_kthread ( thr );
        ASSERT_ERRNO_AND_SYS_EXIT ( kthr, E_DONT_EXIST );
        thrmsg = k_get_thrmsg ( kthr );
        kmsgq = &thrmsg->msgq;
    }
    else if ( dest_type == MSG_QUEUE )
    {
        msgq = dest;
        kgmsgq = msgq->handle;
        ASSERT_ERRNO_AND_SYS_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
                                    E_INVALID_HANDLE );
        kmsgq = &kgmsgq->mq;
    }
    else {
        SYS_EXIT ( E_INVALID_TYPE );
    }

    if ( dest_type == MSG_THREAD || dest_type == MSG_QUEUE )
    {
        /* send message to queue */
        if ( kmsgq->min_prio <= msg->type ) /* msg has required prio. */
        {
            kmsg = kmalloc ( sizeof (kmsg_t) + msg->size );
            ASSERT_ERRNO_AND_SYS_EXIT ( kmsg, E_NO_MEMORY );

            kmsg->msg.type = msg->type;
            kmsg->msg.size = msg->size;
            memcpy ( kmsg->msg.data, msg->data, msg->size );

            list_append ( &kmsgq->msgs, kmsg, &kmsg->list );

            /* is thread waiting for message? */
            if ( k_release_thread ( &kmsgq->thrq ) )
                k_schedule_threads ();

            SYS_EXIT ( SUCCESS );
        }
        else { /* ignore message */
            SYS_EXIT ( E_IGNORED );
        }
    }

    /* must be MSG_SIGNAL */
    //promijenjen uvijet
    //ako je signal_handler postavljen, tada Å¡alji signal
    if ( thrmsg->sig_prio <= msg->type && thrmsg->signal_handler[msg->type] != NULL )
    {
        /* create thread that will service this signal */

        cmsg = k_create_thread_private_storage ( kthr,
                sizeof (msg_t) + msg->size );
        cmsg->type = msg->type;
        cmsg->size = msg->size;
        memcpy ( cmsg->data, msg->data, msg->size );

        new_kthr = k_create_thread (
                       //koji handler???
                       thrmsg->signal_handler[msg->type], cmsg, pi.exit,
                       k_get_thread_prio ( kthr ) + 1, NULL, 0, 1
                   );
        ASSERT_ERRNO_AND_SYS_EXIT ( new_kthr, k_get_errno() );

        k_set_thread_private_storage ( new_kthr, cmsg );

        //SET_ERRNO ( SUCCESS );

        k_schedule_threads ();

        SYS_EXIT ( SUCCESS );
    }
    else { /* ignore signal */
        SYS_EXIT ( E_IGNORED );
    }
}