Ejemplo n.º 1
0
/*
* Cleanup internal resources used by this timer module. It deletes all
* pending timer entries from the backend timer system as well.
*/
int
bcm_timer_module_cleanup(bcm_timer_module_id module_id)
{
	ecos_timer_list_t *list = (ecos_timer_list_t *)module_id;
	ecos_timer_entry_t *entry;
	int key;

	TIMERDBG("list %08x", list);

	/*
	* do nothing if the list has not been initialized
	*/
	if (!(list->flags&TIMER_LIST_FLAG_INIT))
		return -1;

	/*
	* mark the big bang flag here so that no more callbacks
	* shall be scheduled or called from this point on...
	*/
	list->flags |= TIMER_LIST_FLAG_EXIT;

	/*
	* remove all backend timers here so that no timer expires after here.
	*/
	TIMER_LIST_LOCK(list);

	key = INTLOCK();
	for (entry = list->used; entry != NULL; entry = entry->next)
	{
		ecos_del_timer(entry);
	}
	INTUNLOCK(key);

	TIMER_LIST_UNLOCK(list);

	/*
	* have to wait till all expired entries to have been handled
	*/
	for (entry = list->used; entry != NULL; entry = entry->next)
	{
		if ((entry->flags&TIMER_FLAG_DEFERRED) &&
		    !(entry->flags&TIMER_FLAG_FINISHED))
			break;
	}

	cyg_mutex_destroy(&(list->lock));
	/* now it should be safe to blindly free all the resources */
	TIMER_FREE_LOCK_MECHANISM();
	free(list);
	TIMERDBG("done");
	return 0;
}
Ejemplo n.º 2
0
/* add entry into top of list */
static int
put_entry(ecos_timer_entry_t **list, ecos_timer_entry_t *entry)
{
	/* add the entry into top of the list */
	TIMERDBG("list = %08x", *list);
	TIMERDBG("entry = %08x", entry);

	entry->next = *list;
	entry->prev = NULL;

	if (*list != NULL)
		(*list)->prev = entry;
	*list = entry;

	TIMERDBG("new list = %08x", *list);
	return 0;
}
Ejemplo n.º 3
0
int
bcm_timer_delete(bcm_timer_id timer_id)
{
	ecos_timer_entry_t *entry = (ecos_timer_entry_t *)timer_id;
	ecos_timer_list_t *list = entry->list;
	int status;
	int key;

	TIMERDBG("entry %08x timer %08x", entry, entry->timer);

	/* make sure no interrupts can happen */
	key = INTLOCK();

	/* lock the timer list */
	TIMER_LIST_LOCK(list);

	/* remove the entry from the used list first */
	status = remove_entry(&list->used, entry);
	if (status != 0)
		goto exit0;

	/* delete the backend timer */
	ecos_del_timer(entry);

	/* free the entry back to freed list */
	put_entry(&list->freed, entry);

	entry->flags = TIMER_FLAG_NONE;
	entry->list = NULL;
	TIMER_LIST_UNLOCK(list);

	INTUNLOCK(key);

	TIMERDBG("done");
	return 0;

	/* error handling */
exit0:
	TIMER_LIST_UNLOCK(list);
	INTUNLOCK(key);
	return status;
}
Ejemplo n.º 4
0
int
bcm_timer_cancel(bcm_timer_id timer_id)
{
	ecos_timer_entry_t *entry = (ecos_timer_entry_t *)timer_id;

	TIMERDBG("entry %08x timer %08x", entry, entry->timer);

	ecos_del_timer(entry);
	entry->flags &= ~TIMER_FLAG_ARMED;
	return 0;
}
Ejemplo n.º 5
0
int dd_timer_create( clockid_t clock_id,	/* clock ID (always CLOCK_REALTIME) */
		  struct sigevent *evp,	/* user event handler */
		  timer_t * pTimer	/* ptr to return value */
     )
{
    struct event *event;

    if( clock_id != CLOCK_REALTIME )
    {
	TIMERDBG( "timer_create can only support clock id CLOCK_REALTIME" );
	exit( 1 );
    }

    if( evp != NULL )
    {
	if( evp->sigev_notify != SIGEV_SIGNAL || evp->sigev_signo != SIGALRM )
	{
	    TIMERDBG
		( "timer_create can only support signalled alarms using SIGALRM" );
	    exit( 1 );
	}
    }

    event = event_freelist;
    if( event == NULL )
    {
	print_event_queue(  );
    }
    assert( event != NULL );

    event->flags = TFLAG_NONE;

    event_freelist = event->next;
    event->next = NULL;

    check_event_queue(  );

    *pTimer = ( timer_t ) event;

    return 0;
}
Ejemplo n.º 6
0
int
bcm_timer_settime(bcm_timer_id timer_id, const struct itimerspec *timer_spec)
{
	unsigned int ms;
	ecos_timer_entry_t *entry = (ecos_timer_entry_t *)timer_id;
	TIMERDBG("entry %08x timer %08x", entry, entry->timer);

	ms = (timer_spec->it_value.tv_sec*1000) +
		((timer_spec->it_value.tv_nsec/1000)/1000);

	return ecos_add_timer(entry, ms, 1) ? 0 : 1;
}
Ejemplo n.º 7
0
/* alloc entry from top of list */
static int
get_entry(ecos_timer_entry_t **list, ecos_timer_entry_t **entry)
{
	/* take an entry from top of the list */
	TIMERDBG("list = %08x", *list);

	*entry = *list;
	if (*entry == NULL)
		return -1;

	*list = (*entry)->next;
	if (*list != NULL)
		(*list)->prev = NULL;

	TIMERDBG("new list = %08x", *list);
	(*entry)->next = NULL;
	(*entry)->prev = NULL;

	TIMERDBG("entry = %08x", *entry);
	return 0;
}
Ejemplo n.º 8
0
int
bcm_timer_connect(bcm_timer_id timer_id, bcm_timer_cb func, int data)
{
	ecos_timer_entry_t *entry = (ecos_timer_entry_t *)timer_id;

	entry->func = func;
	entry->data = data;
	TIMERDBG("entry %08x timer %08x func %08x data %08x",
	         entry, entry->timer, entry->func, entry->data);

	entry->flags |= TIMER_FLAG_ARMED;
	return 0;
}
Ejemplo n.º 9
0
/* remove entry from list */
static int
remove_entry(ecos_timer_entry_t **list, ecos_timer_entry_t *entry)
{
	/* remove the entry from the list */
	TIMERDBG("list = %08x", *list);
	TIMERDBG("entry = %08x", entry);

	if (entry->prev != NULL)
		entry->prev->next = entry->next;

	if (entry->next != NULL)
		entry->next->prev = entry->prev;

	if (*list == entry)
		*list = entry->next;

	entry->next = NULL;
	entry->prev = NULL;

	TIMERDBG("new list = %08x", *list);
	return 0;
}
Ejemplo n.º 10
0
/*
* Initialize internal resources used in the timer module. It must be called
* before any other timer function calls. The param 'timer_entries' is used
* to pre-allocate fixed number of timer entries.
*/
int
bcm_timer_module_init(int timer_entries, bcm_timer_module_id *module_id)
{
	int size = timer_entries*sizeof(ecos_timer_entry_t);
	ecos_timer_list_t *list;
	int i;

	TIMERDBG("entries %d", timer_entries);

	/* alloc fixed number of entries upfront */
	list = malloc(sizeof(ecos_timer_list_t)+size);
	if (list == NULL)
		goto exit0;

	cyg_mutex_init(&(list->lock));
	list->flags = TIMER_LIST_FLAG_NONE;
	list->entry = (ecos_timer_entry_t *)(list + 1);
	list->entries = timer_entries;
	TIMERDBG("entry %08x", list->entry);

	/* init the timer entries to form two list - freed and used */
	list->freed = NULL;
	list->used = NULL;
	memset(list->entry, 0, timer_entries*sizeof(ecos_timer_entry_t));

	for (i = 0; i < timer_entries; i ++)
	{
		put_entry(&list->freed, &list->entry[i]);
	}
	list->flags = TIMER_LIST_FLAG_INIT;
	*module_id = (bcm_timer_module_id)list;

	TIMERDBG("list %08x freed %08x used %08x", list, list->freed, list->used);
	return 0;

exit0:
	return -1;
}
Ejemplo n.º 11
0
int
bcm_timer_create(bcm_timer_module_id module_id, bcm_timer_id *timer_id)
{
	ecos_timer_list_t *list = (ecos_timer_list_t *)module_id;
	ecos_timer_entry_t *entry;
	int status = -1;

	TIMERDBG("list %08x", list);

	/* lock the timer list */
	TIMER_LIST_LOCK(list);

	/* check if timer is allowed */
	if (list->flags & TIMER_LIST_FLAG_EXIT)
		goto exit0;

	/* alloc an entry first */
	status = get_entry(&list->freed, &entry);
	if (status != 0)
		goto exit0;

	/* add the entry into used list */
	put_entry(&list->used, entry);

	entry->flags = TIMER_FLAG_IN_USE;
	entry->list = list;
	*timer_id = (bcm_timer_id)(void *)entry;

	TIMER_LIST_UNLOCK(list);
	TIMERDBG("entry %08x timer %08x", entry, entry->timer);
	return 0;

	/* error handling */
exit0:
	TIMER_LIST_UNLOCK(list);
	return status;
}
Ejemplo n.º 12
0
int dd_timer_delete( timer_t timerid	/* timer ID */
     )
{
    struct event *event = ( struct event * )timerid;

    if( event->flags & TFLAG_DELETED )
    {
	TIMERDBG( "Cannot delete a deleted event" );
	return 1;
    }

    dd_timer_cancel( timerid );

    event->flags |= TFLAG_DELETED;

    event->next = event_freelist;
    event_freelist = event;

    return 0;
}
Ejemplo n.º 13
0
int dd_timer_settime( timer_t timerid,	/* timer ID */
		   int flags,	/* absolute or relative */
		   const struct itimerspec *value,	/* time to be set */
		   struct itimerspec *ovalue	/* previous time set (NULL=no 
						 * result) */
     )
{
    struct itimerval itimer;
    struct event *event = ( struct event * )timerid;
    struct event **ppevent;

    TIMESPEC_TO_TIMEVAL( &event->it_interval, &value->it_interval );
    TIMESPEC_TO_TIMEVAL( &event->it_value, &value->it_value );

    /*
     * if .it_value is zero, the timer is disarmed 
     */
    if( !timerisset( &event->it_value ) )
    {
	dd_timer_cancel( timerid );
	return 0;
    }

    dd_block_timer(  );

#ifdef TIMER_PROFILE
    event->expected_ms =
	( event->it_value.tv_sec * MS_PER_SEC ) +
	( event->it_value.tv_usec / US_PER_MS );
    event->start = uclock(  );
#endif
    if( event->next )
    {
	TIMERDBG
	    ( "calling timer_settime with a timer that is already on the queue." );
    }

    /*
     * We always want to make sure that the event at the head of the queue
     * has a timeout greater than the itimer granularity. Otherwise we end up 
     * with the situation that the time remaining on an itimer is greater
     * than the time at the head of the queue in the first place. 
     */
    timerroundup( &event->it_value, g_granularity );

    timerclear( &itimer.it_value );
    getitimer( ITIMER_REAL, &itimer );
    if( timerisset( &itimer.it_value ) )
    {
	// reset the top timer to have an interval equal to the remaining
	// interval 
	// when the timer was cancelled.
	if( event_queue )
	{
	    if( timercmp
		( &( itimer.it_value ), &( event_queue->it_value ), > ) )
	    {
		// it is an error if the amount of time remaining is more
		// than the amount of time 
		// requested by the top event.
		// 
		TIMERDBG( "timer_settime: TIMER ERROR!" );

	    }
	    else
	    {
		// some portion of the top event has already expired.
		// Reset the interval of the top event to remaining
		// time left in that interval.
		// 
		event_queue->it_value = itimer.it_value;

		// if we were the earliest timer before now, we are still the 
		// earliest timer now.
		// we do not need to reorder the list.
	    }
	}
    }