/*!
 * Delete global message queue
 */
int sys__delete_msg_queue ( void *p )
{
	/* parameter on thread stack */
	msg_q *msgq;
	/* local variables */
	kgmsg_q *gmsgq;

	msgq = *( (msg_q **) p );

	ASSERT_ERRNO_AND_EXIT ( msgq, E_INVALID_HANDLE );
	msgq = U2K_GET_ADR ( msgq, k_get_active_process () );

	gmsgq = msgq->handle;
	ASSERT_ERRNO_AND_EXIT ( gmsgq->id == msgq->id, E_INVALID_HANDLE );

	k_msgq_clean ( &gmsgq->mq );

	k_release_all_threads ( &gmsgq->mq.thrq );

	k_free_unique_id ( gmsgq->id );

	kfree ( gmsgq );

	msgq->id = 0;
	msgq->handle = NULL;

	EXIT ( SUCCESS );
}
/*!
 * 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;
}
/*!
 * 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.º 4
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;
}
/*!
 * 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 );
}
/*!
 * Delete global message queue
 */
int sys__delete_msg_queue ( msg_q *msgq )
{
	kgmsg_q *gmsgq;

	ASSERT_ERRNO_AND_EXIT ( msgq, E_INVALID_HANDLE );

	gmsgq = msgq->handle;
	ASSERT_ERRNO_AND_EXIT ( gmsgq->id == msgq->id, E_INVALID_HANDLE );

	k_msgq_clean ( &gmsgq->mq );

	k_release_all_threads ( &gmsgq->mq.thrq );

	k_free_unique_id ( gmsgq->id );

	kfree ( gmsgq );

	msgq->id = 0;
	msgq->handle = NULL;

	EXIT ( SUCCESS );
}
/*!
 * Iterate through active alarms and activate newly expired ones
 */
static int k_schedule_alarms ()
{
	kalarm_t *first;
	time_t time, ref_time;
	int resched_thr = 0;
	kprocess_t *proc;

	arch_get_time ( &time );
	ref_time = time;
	time_add ( &ref_time, &threshold );

	/* should any alarm be activated? */
	first = list_get ( &kalarms, FIRST );
	while ( first != NULL )
	{
		if ( time_cmp ( &first->alarm.exp_time, &ref_time ) <= 0 )
		{
			/* 'activate' alarm */

			/* but first remove alarm from list */
			first = list_remove ( &kalarms, FIRST, NULL );

			if ( first->alarm.flags & ALARM_PERIODIC )
			{
				/* calculate next activation time */
				time_add ( &first->alarm.exp_time,
					   &first->alarm.period );
				/* put back into list */
				list_sort_add ( &kalarms, first, &first->list,
						alarm_cmp );
			}
			else {
				first->active = 0;
			}

			if ( first->alarm.action )
			{
				/* call directly:

				first->alarm.action ( first->alarm.param );

				   or create new thread for that job: */

				if ( first->thread )
				{ /* alarm scheduled by thread */
				proc = k_get_thread_process ( first->thread );
				k_create_thread (
					first->alarm.action,
					first->alarm.param,
					proc->pi->exit,
					k_get_thread_prio ( first->thread ) + 1,
					NULL, 0, 1,
					proc
				);
				resched_thr++;
				}
				else { /* alarm scheduled by kernel */
				first->alarm.action ( first->alarm.param );
				}
			}

			resched_thr += k_release_all_threads ( &first->queue );

			first = list_get ( &kalarms, FIRST );
		}
		else {
			break;
		}
	}

	first = list_get ( &kalarms, FIRST );
	if ( first )
	{
		ref_time = first->alarm.exp_time;
		time_sub ( &ref_time, &time );
		arch_timer_set ( &ref_time, k_timer_interrupt );
	}

	return resched_thr;
}