/*! initialize thread structures and create idle thread */
void k_threads_init ()
{
	extern kdevice_t *u_stdin, *u_stdout;
	kthread_t *kthr;
	int prio;

	list_init ( &all_threads );

	/* queue for ready threads is empty */
	init_ready_list ();

	/* setup programs */
	pi.stdin = u_stdin;
	pi.stdout = u_stdout;

	pi.heap = kmalloc ( PROG_HEAP_SIZE );
	pi.heap_size = PROG_HEAP_SIZE;

	prio = pi.prio;
	if ( !prio )
		prio = THR_DEFAULT_PRIO;

	/* idle thread */
	kthr = k_create_thread ( idle_thread, NULL, NULL, 0, NULL, 0, 1 );

	/* first "user" thread */
	k_create_thread (pi.init, NULL, pi.exit, prio, NULL, 0, 1 );

	active_thread = NULL;

	k_schedule_threads ();
}
/*!
 * End current thread (exit from it)
 * \param status Exit status number
 */
int sys__thread_exit ( void *p )
{
	int status;

	status = *( (int *) p );

	active_thread->state = THR_STATE_PASSIVE;
	active_thread->ref_cnt--;
	active_thread->exit_status = status;

#ifdef	MESSAGES
	k_msgq_clean ( &active_thread->msg.msgq );
#endif
	/* release thread stack */
	if ( active_thread->stack )
		kfree ( active_thread->stack );

	k_delete_thread_private_storage ( active_thread,
					  active_thread->private_storage );

	if ( !active_thread->ref_cnt )
	{
		k_remove_thread_descriptor ( active_thread );

		active_thread = NULL;
	}
	else {
		k_release_all_threads ( &active_thread->join_queue );
	}

	k_schedule_threads ();

	return 0;
}
/*!
 * 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 );
}
/*!
 * Lock monitor (or block trying)
 */
int sys__monitor_lock ( monitor_t *monitor )
{
	kmonitor_t *kmonitor;

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

	disable_interrupts ();

	kmonitor = monitor->ptr;

	SET_ERRNO ( SUCCESS );

	if ( !kmonitor->lock )
	{
		kmonitor->lock = TRUE;
		kmonitor->owner = k_get_active_thread ();
	}
	else {
		k_enqueue_thread ( NULL, &kmonitor->queue );
		k_schedule_threads ();
	}

	enable_interrupts ();

	EXIT ( SUCCESS );
}
/* Add alarm to alarm pool if its expiration time is defined
   If expiration time is in the past, alarm will be immediately activated!
 */
static void k_alarm_add ( kalarm_t *kalarm )
{
	int reschedule = 0;

	/* if exp_time is given (>0) add it into active alarms */
	if ( kalarm->alarm.exp_time.sec + kalarm->alarm.exp_time.nsec > 0 )
	{
		kalarm->active = 1;
		list_sort_add ( &kalarms, kalarm, &kalarm->list, alarm_cmp );
	}
	else {
		kalarm->active = 0;
	}

	reschedule = k_schedule_alarms (); /* this or other alarm may expire */

	SET_ERRNO ( SUCCESS );

	/* block thread? */
	if ( kalarm->active && ( kalarm->alarm.flags & IPC_WAIT ) )
	{
		k_enqueue_thread ( NULL, &kalarm->queue );
		reschedule = 1;
	}

	if ( reschedule )
		k_schedule_threads ();
}
/*!
 * Delete alarm
 * \param param Alarm
 * \returns status (0 for success)
 */
int k_alarm_remove ( void *id )
{
	kalarm_t *kalarm;
	int reschedule = 0;

	kalarm = id;

	ASSERT ( kalarm && kalarm->magic == ALARM_MAGIC );

	/* remove from active alarms (if it was there) */
	if ( kalarm->active )
		list_remove ( &kalarms, FIRST, &kalarm->list );

#ifdef DEBUG
	kalarm->magic = 0;
#endif

	SET_ERRNO ( SUCCESS );

	/* release all waiting threads, if any */
	reschedule = k_release_all_threads ( &kalarm->queue );

	kfree ( kalarm );

	reschedule += k_schedule_alarms ();

	if ( reschedule )
		k_schedule_threads ();

	RETURN ( SUCCESS );
}
Exemplo n.º 7
0
/*!
 * Create new thread (params on user stack!)
 * \param func Starting function
 * \param param Parameter for starting function
 * \param prio Priority for new thread
 * \param thr_desc User level thread descriptor
 * (parameters are on calling thread stack)
 */
int sys__create_thread ( void *p )
{
	void *func;
	void *param;
	int prio;
	thread_t *thr_desc;

	kthread_t *kthr;

	func = *( (void **) p ); p += sizeof (void *);

	param = *( (void **) p ); p += sizeof (void *);

	prio = *( (int *) p ); p += sizeof (int);

	kthr = k_create_thread (func, param, active_thread->proc->pi->exit, prio,
				NULL, 0, 1, active_thread->proc );

	ASSERT_ERRNO_AND_EXIT ( kthr, E_NO_MEMORY );

	thr_desc = *( (void **) p );
	if ( thr_desc )
	{
		thr_desc = U2K_GET_ADR ( thr_desc, active_thread->proc );
		thr_desc->thread = kthr;
		thr_desc->thr_id = kthr->id;
	}

	SET_ERRNO ( SUCCESS );

	k_schedule_threads ();

	RETURN ( SUCCESS );
}
/*!
 * 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 );
}
/*!
 * Create new thread
 * \param func Starting function
 * \param param Parameter for starting function
 * \param prio Priority for new thread
 * \param thr_desc User level thread descriptor
 * (parameters are on calling thread stack)
 */
int sys__create_thread ( void *p )
{
	void *func;
	void *param;
	int prio;
	thread_t *thr_desc;

	kthread_t *kthr;

	func = *( (void **) p ); p += sizeof (void *);

	param = *( (void **) p ); p += sizeof (void *);

	prio = *( (int *) p ); p += sizeof (int);

	kthr = k_create_thread ( func, param, pi.exit, prio, NULL, 0, 1 );

	thr_desc = *( (void **) p );
	if ( thr_desc )
	{
		thr_desc->thread = kthr;
		thr_desc->thr_id = kthr->id;
	}

	SET_ERRNO ( SUCCESS );

	k_schedule_threads ();

	RETURN ( 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;
}
Exemplo n.º 11
0
/*!
 * Wait for thread termination
 * \param thread Thread descriptor (user level descriptor)
 * \param wait Wait if thread not finished (!=0) or not (0)?
 * \return 0 if thread already gone; -1 if not finished and 'wait' not set;
 *         'thread exit status' otherwise
 */
int sys__wait_for_thread ( void *p )
{
	thread_t *thread;
	int wait;
	kthread_t *kthr;
	int ret_value = 0;

	thread = U2K_GET_ADR ( *( (void **) p ), active_thread->proc );
	p += sizeof (void *);

	wait = *( (int *) p );

	ASSERT_ERRNO_AND_EXIT ( thread && thread->thread, E_INVALID_HANDLE );

	kthr = thread->thread;

	if ( kthr->id != thread->thr_id ) /* at 'kthr' is now something else */
	{
		ret_value = -SUCCESS;
		SET_ERRNO ( SUCCESS );
	}
	else if ( kthr->state != THR_STATE_PASSIVE && !wait )
	{
		ret_value = -E_NOT_FINISHED;
		SET_ERRNO ( E_NOT_FINISHED );
	}
	else if ( kthr->state != THR_STATE_PASSIVE )
	{
		kthr->ref_cnt++;

		ret_value = -E_RETRY; /* retry (collect thread status) */
		SET_ERRNO ( E_RETRY );

		k_enqueue_thread ( NULL, &kthr->join_queue );

		k_schedule_threads ();
	}
	else {
		/* kthr->state == THR_STATE_PASSIVE, but thread descriptor still
		   not freed - some thread still must collect its status */
		SET_ERRNO ( SUCCESS );
		ret_value = kthr->exit_status;

		kthr->ref_cnt--;

		if ( !kthr->ref_cnt )
			k_remove_thread_descriptor ( kthr );
	}

	return ret_value;
}
Exemplo n.º 12
0
/*!
 * End current thread (exit from it)
 * \param status Exit status number
 */
int sys__thread_exit ( void *p )
{
	int status;

	status = *( (int *) p );

	active_thread->state = THR_STATE_PASSIVE;
	active_thread->ref_cnt--;
	active_thread->exit_status = status;

	active_thread->proc->thr_count--;

#ifdef	MESSAGES
	k_msgq_clean ( &active_thread->msg.msgq );
#endif
	/* release thread stack */
	if ( active_thread->stack )
	{
		if ( active_thread->proc->m.start ) /* user level thread */
			ffs_free ( active_thread->proc->stack_pool,
				   active_thread->stack );
		else /* kernel level thread */
			kfree ( active_thread->stack );
	}

	k_delete_thread_private_storage ( active_thread,
					  active_thread->private_storage );

	if ( active_thread->proc->thr_count == 0 && active_thread->proc->pi )
	{
		/* last (non-kernel) thread - remove process */
		ASSERT ( list_remove ( &procs, FIRST, &active_thread->proc->all ) );
		active_thread->proc->prog->started = FALSE;
		kfree ( active_thread->proc );
	}

	if ( !active_thread->ref_cnt )
	{
		k_remove_thread_descriptor ( active_thread );

		active_thread = NULL;
	}
	else {
		k_release_all_threads ( &active_thread->join_queue );
	}

	k_schedule_threads ();

	return 0;
}
/*! Lock device */
int k_device_lock ( kdevice_t *dev, int wait )
{
	if ( !wait && dev->locked )
		return -1;

	if ( dev->locked )
	{
		k_enqueue_thread ( NULL, &dev->thrq );
		k_schedule_threads ();
	}

	dev->locked = TRUE;

	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 );
}
/*!
 * Destroy monitor (and unblock all threads blocked on it)
 */
int sys__monitor_queue_destroy ( monitor_q *queue )
{
	kmonitor_q *kqueue;

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

	disable_interrupts ();

	kqueue = queue->ptr;

	if ( k_release_all_threads ( &kqueue->queue ) )
		k_schedule_threads ();

	kfree ( kqueue );
	queue->ptr = NULL;

	enable_interrupts ();

	EXIT ( SUCCESS );
}
/*!
 * Destroy monitor (and unblock all threads blocked on it)
 */
int sys__monitor_destroy ( monitor_t *monitor )
{
	kmonitor_t *kmonitor;

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

	disable_interrupts ();

	kmonitor = monitor->ptr;

	if ( k_release_all_threads ( &kmonitor->queue ) )
		k_schedule_threads ();

	kfree ( kmonitor );
	monitor->ptr = NULL;

	enable_interrupts ();

	EXIT ( SUCCESS );
}
Exemplo n.º 17
0
/*! initialize thread structures and create idle thread */
void k_threads_init ()
{
	kthread_t *kthr;

	list_init ( &all_threads );
	list_init ( &procs );

	/* queue for ready threads is empty */
	init_ready_list ();

	/* initially create 'idle thread' */
	kernel_proc.prog = NULL;
	kernel_proc.stack_pool = NULL;
	kernel_proc.m.start = NULL;
	kernel_proc.m.size = (size_t) 0xffffffff;

	kthr = k_create_thread ( idle_thread, NULL, NULL, 0, NULL, 0, 1,
				&kernel_proc );

	active_thread = NULL;

	k_schedule_threads ();
}
//int sys__wait_for_alarm ( void *alarm, int wait )
int sys__wait_for_alarm ( void *p )
{
	void *id;
	int wait;
	kalarm_t *kalarm;
	int retval;

	id = *( (void **) p );
	ASSERT_ERRNO_AND_EXIT ( id, E_INVALID_HANDLE );


	p += sizeof (void *);
	wait =  *( (int *)   p );

	kalarm = id;

	ASSERT_ERRNO_AND_EXIT ( kalarm && kalarm->magic == ALARM_MAGIC,
				E_INVALID_HANDLE );

	retval = 0;
	SET_ERRNO ( SUCCESS );

	if ( kalarm->active )
	{
		if ( wait & IPC_WAIT )
		{
			k_enqueue_thread ( NULL, &kalarm->queue );
			k_schedule_threads ();
		}
		else {
			SET_ERRNO ( E_NOT_EXPIRED );
			retval = -E_NOT_EXPIRED;
		}
	}

	return retval;
}
Exemplo n.º 19
0
/*! Receive message from queue (global or from own thread message queue) */
int sys__msg_recv ( int src_type, void *src, msg_t *msg, int type, size_t size,
                    uint flags )
{
    kthread_t *kthr;
    kthrmsg_qs *thrmsg;
    kgmsg_q *kgmsgq;
    kmsg_q *kmsgq;
    msg_q *msgq;
    kmsg_t *kmsg;

    SYS_ENTRY();

    ASSERT_ERRNO_AND_SYS_EXIT (
        src_type == MSG_THREAD || ( src_type == MSG_QUEUE && src ),
        E_INVALID_TYPE );
    ASSERT_ERRNO_AND_SYS_EXIT ( msg && size > 0, E_INVALID_HANDLE );

    if ( src_type == MSG_THREAD )
    {
        kthr = k_get_active_thread ();
        thrmsg = k_get_thrmsg ( kthr );
        kmsgq = &thrmsg->msgq;
    }
    else { /* src_type == MSG_QUEUE */
        msgq = src;
        kgmsgq = msgq->handle;
        ASSERT_ERRNO_AND_SYS_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
                                    E_INVALID_HANDLE );
        kmsgq = &kgmsgq->mq;
    }

    /* get first message from queue */
    kmsg = list_get ( &kmsgq->msgs, FIRST );

    if ( type != 0 ) /* type != 0 => search for first message 'type' */
        while ( kmsg && kmsg->msg.type != type )
            kmsg = list_get_next ( &kmsg->list );

    if ( kmsg ) /* have message */
    {
        if ( size < kmsg->msg.size )
        {
            msg->size = 0;
            SYS_EXIT ( E_TOO_BIG );
        }

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

        kmsg = list_remove ( &kmsgq->msgs, FIRST, &kmsg->list );
        ASSERT ( kmsg );
        kfree ( kmsg );

        SYS_EXIT ( SUCCESS );
    }
    else { /* queue empty! */
        if ( !( flags & IPC_WAIT ) )
            SYS_EXIT ( E_EMPTY );

        //SET_ERRNO ( E_RETRY );
        /* block thread */
        k_enqueue_thread ( NULL, &kmsgq->thrq );

        k_schedule_threads ();

        SYS_EXIT ( E_RETRY );
    }
}
Exemplo n.º 20
0
/*!
 * Start program defined by 'prog' (loaded as module) as new process:
 * - initialize environment (stack area for threads, stdin, stdout) and start
 *   it's first thread
 * \param prog_name Program name (as given with module)
 * \param param Command line arguments for starting thread (if not NULL)
 * \param prio Priority for starting thread
 * \return Pointer to descriptor of created process
 */
kthread_t *k_proc_start ( char *prog_name, void *param, int prio )
{
	extern kdevice_t *u_stdin, *u_stdout;
	extern list_t progs;
	kprog_t *prog;
	kprocess_t *proc;
	kthread_t *kthr;
	char **args = NULL, *arg, *karg, **kargs;
	size_t argsize;
	int i;

	prog = list_get ( &progs, FIRST );
	while ( prog && strcmp ( prog->prog_name, prog_name ) )
		prog = list_get_next ( &prog->all );

	if ( !prog )
		return NULL;

	if ( prog->started )
		return NULL;

	/* create new process */
	proc = kmalloc ( sizeof ( kprocess_t) );
	ASSERT ( proc );

	proc->prog = prog;
	proc->m.size = prog->m.size;
	proc->m.start = proc->pi = prog->pi;

	proc->pi->stdin = u_stdin;
	proc->pi->stdout = u_stdout;

	/* initialize memory pool for threads stacks */
	proc->stack_pool = ffs_init ( U2K_GET_ADR ( proc->pi->stack, proc ),
				      prog->pi->stack_size );

	proc->thr_count = 0;

	if ( !prio )
		prio = proc->pi->prio;
	if ( !prio )
		prio = THR_DEFAULT_PRIO;

	if ( param ) /* have arguments? */
	{
		/* copy command line arguments from kernel space to process;
		   (use process stack space for arguments) */
		kargs = param;
		for ( i = 0; kargs[i]; i++ ) ;
		argsize = ( (size_t) kargs[i-1] + strlen( kargs[i-1] ) + 1 )
			  - (size_t) param;
		if ( argsize > 0 )
		{
			args = ffs_alloc ( proc->stack_pool, argsize );
			arg = (void *) args + (i + 1) * sizeof (void *);
			kargs = param;
			i = 0;
			do {
				karg = kargs[i];
				strcpy ( arg, karg );
				args[i++] = K2U_GET_ADR ( arg, proc );
				arg += strlen ( arg ) + 1;
			}
			while ( kargs[i] );
			args[i] = NULL;
			args = K2U_GET_ADR ( args, proc );
		}

		kfree ( param );
	}
	kthr = k_create_thread ( proc->pi->init, args, NULL, prio, NULL, 0, 1,
				proc );

	list_append ( &procs, proc, &proc->all );

	prog->started = 1;

	k_schedule_threads ();

	return kthr;
}
/*!
 * Called from interrupt handler when an alarm has expired
 */
static void k_timer_interrupt ()
{
	if ( k_schedule_alarms () )
		k_schedule_threads ();
}
/*!
 * Receive message from queue (global or from own thread message queue)
 */
int sys__msg_recv ( void *p )
{
	/* parameters on thread stack */
	int src_type;	/* MSG_QUEUE or MSG_THREAD 		*/
	void *src;	/* (msg_q *) or (thread_t *)		*/
	msg_t *msg;	/* { type, size, data[0..size-1] }	*/
	int type;	/* message type (identifier) */
	size_t size;	/* size of 'data' member */
	uint flags;
	/* local variables */
	kthread_t *kthr;
	kthrmsg_qs *thrmsg;
	kgmsg_q *kgmsgq;
	kmsg_q *kmsgq;
	msg_q *msgq;
	kmsg_t *kmsg;

	src_type = *( (int *) p );	p += sizeof (int);
	src = *( (void **) p );		p += sizeof (void *);
	msg = *( (msg_t **) p );	p += sizeof (msg_t *);
	type = *( (int *) p );		p += sizeof (int);
	size = *( (size_t *) p );	p += sizeof (size_t);
	flags = *( (uint *) p );

	ASSERT_ERRNO_AND_EXIT ( src && msg, E_INVALID_HANDLE );

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

	ASSERT_ERRNO_AND_EXIT ( src_type == MSG_THREAD || src_type == MSG_QUEUE,
				E_INVALID_TYPE );

	if ( src_type == MSG_THREAD )
	{
		kthr = k_get_active_thread ();
		thrmsg = k_get_thrmsg ( kthr );
		kmsgq = &thrmsg->msgq;
	}
	else { /* src_type == MSG_QUEUE */
		msgq = src;
		kgmsgq = msgq->handle;
		ASSERT_ERRNO_AND_EXIT ( kgmsgq && kgmsgq->id == msgq->id,
					E_INVALID_HANDLE );
		kmsgq = &kgmsgq->mq;
	}

	/* get first message from queue */
	kmsg = list_get ( &kmsgq->msgs, FIRST );

	if ( type != 0 ) /* type != 0 => search for first message 'type' */
		while ( kmsg && kmsg->msg.type != type )
			kmsg = list_get_next ( &kmsg->list );

	if ( kmsg ) /* have message */
	{
		if ( size < kmsg->msg.size )
		{
			msg->size = 0;
			EXIT ( E_TOO_BIG );
		}

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

		kmsg = list_remove ( &kmsgq->msgs, FIRST, &kmsg->list );
		ASSERT ( kmsg );
		kfree ( kmsg );

		EXIT ( SUCCESS );
	}
	else { /* queue empty! */
		if ( !( flags & IPC_WAIT ) )
			EXIT ( E_EMPTY );

		SET_ERRNO ( E_RETRY );
		/* block thread */
		k_enqueue_thread ( NULL, &kmsgq->thrq );

		k_schedule_threads ();

		RETURN ( E_RETRY );
	}
}
/*!
 * 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 );
	}
}
Exemplo n.º 24
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 );
    }
}