eventflag rewrite

This commit is contained in:
NIIBE Yutaka
2016-05-18 16:52:00 +09:00
parent 7f009dbb5d
commit db413813b6
7 changed files with 129 additions and 109 deletions

View File

@@ -1,7 +1,11 @@
2016-05-18 NIIBE Yutaka <gniibe@fsij.org> 2016-05-18 NIIBE Yutaka <gniibe@fsij.org>
* eventflag.c: Update using chopstx_poll.
* chopstx.c (requeue): New. * chopstx.c (requeue): New.
(chopstx_mutex_lock, chopstx_join): Fix by requeue. (chopstx_mutex_lock, chopstx_join): Fix by requeue.
(chopstx_main_init): Remove.
(chopstx_setpriority): New.
* example-cdc/usb-cdc.c: Prepare for multiple TTYs. * example-cdc/usb-cdc.c: Prepare for multiple TTYs.
@@ -245,7 +249,7 @@
comply AAPCS (ARM Architecture Procedure Call Standard). comply AAPCS (ARM Architecture Procedure Call Standard).
(chx_init): Initialize W. (chx_init): Initialize W.
* example-cdc/{usb_stm32f103.c,usb_lld.h}: Update from Gnuk. * example-cdc/usb_stm32f103.c, usb_lld.h: Update from Gnuk.
* example-cdc/usb-cdc.c: Update. * example-cdc/usb-cdc.c: Update.
2015-11-05 Niibe Yutaka <gniibe@fsij.org> 2015-11-05 Niibe Yutaka <gniibe@fsij.org>
@@ -263,7 +267,7 @@
* chopstx.c (q_exit): Remove. * chopstx.c (q_exit): Remove.
(chx_init, chx_exit): Remove access to Q_EXIT. (chx_init, chx_exit): Remove access to Q_EXIT.
(chx_release_irq_thread): Fix removing form the list. (chx_release_irq_thread): Fix removing from the list.
2015-09-11 Niibe Yutaka <gniibe@fsij.org> 2015-09-11 Niibe Yutaka <gniibe@fsij.org>

25
NEWS
View File

@@ -3,16 +3,32 @@ NEWS - Noteworthy changes
* Major changes in Chopstx 0.11 * Major changes in Chopstx 0.11
Released 2016-0X-XX Released 2016-05-19
** New feature: polling ** New feature: polling
New function chopstx_poll is added to watch multiple condition New function chopstx_poll is added to watch multiple condition
variables, threads' exit, or IRQ, simultaneously with timeout. variables, threads' exit, or IRQ, simultaneously with timeout.
** Remove the function chopstx_release_irq ** Change API of eventflag
IRQ is enabled only a thread is blocked in polling. When it (the
The initialization function eventflag_init only has EV. The eventflag
is can be waited with timeout or can be waited with no timeout,
dynamically. It is not determined at initialization time. Besides,
the eventflag can be waited by any threads.
** Removal of the function chopstx_release_irq
IRQ is enabled only when a thread is blocked in polling. When it (the
thread in polling) is canceled, IRQ is disabled. thread in polling) is canceled, IRQ is disabled.
** Removal of the function chopstx_main_init
Removed because it's too special. Please use chopstx_setpriority
instead.
** New function: chopstx_setpriority
This function is not recommended in general. It is only added to
offer the purpose of chopstx_main_init.
** Function chopstx_intr_wait is deprecated ** Function chopstx_intr_wait is deprecated
Use of chopstx_poll is recommended. Use of chopstx_poll is recommended.
@@ -28,6 +44,9 @@ doesn't have complex exception mechism of ICI/IT (which is supported
on Cortex-M3), it is actually possible to implement the context switch on Cortex-M3), it is actually possible to implement the context switch
in user mode. This is done. in user mode. This is done.
** New sys.c (3.0)
Don't touch NVIC in usb_lld_sys_init.
* Major changes in Chopstx 0.10 * Major changes in Chopstx 0.10

View File

@@ -333,6 +333,11 @@ struct chx_thread { /* inherits PQ */
struct chx_cleanup *clp; struct chx_cleanup *clp;
}; };
struct chx_poll_head {
uint16_t type;
uint16_t ready;
};
static void static void
chx_cpu_sched_lock (void) chx_cpu_sched_lock (void)
@@ -692,27 +697,6 @@ chx_init (struct chx_thread *tp)
} }
/**
* chopstx_main_init - initialize main thread
* @prio: priority
*
* Initialize main thread with @prio.
* The thread main is created with priority CHX_PRIO_MAIN_INIT,
* and it runs with that priority until this routine will is called.
*/
void
chopstx_main_init (chopstx_prio_t prio)
{
struct chx_thread *tp = (struct chx_thread *)chopstx_main;
tp->prio_orig = prio;
if (prio >= CHOPSTX_PRIO_INHIBIT_PREEMPTION)
chx_cpu_sched_lock ();
tp->prio = prio;
}
static void static void
chx_request_preemption (uint16_t prio) chx_request_preemption (uint16_t prio)
@@ -1137,6 +1121,8 @@ chx_snooze (uint32_t state, uint32_t *usec_p)
* *
* Sleep for micro seconds, specified by @var. * Sleep for micro seconds, specified by @var.
* Another thread can clear @var to stop the caller going into sleep. * Another thread can clear @var to stop the caller going into sleep.
*
* This function is DEPRECATED. Please use chopstx_poll.
*/ */
void void
chopstx_usec_wait_var (uint32_t *var) chopstx_usec_wait_var (uint32_t *var)
@@ -1524,13 +1510,13 @@ chopstx_cleanup_pop (int execute)
/** /**
* chopstx_exit - Terminate the execution of thread * chopstx_exit - Terminate the execution of running thread
* @retval: Return value (to be caught by a joining thread) * @retval: Return value (to be caught by a joining thread)
* *
* Calling this function terminates the execution of thread, after * Calling this function terminates the execution of running thread,
* calling clean up functions. If the calling thread still holds * after calling clean up functions. If the calling thread still
* mutexes, they will be released. If the calling thread claiming * holds mutexes, they will be released. This function never
* IRQ, it will be released, too. This function never returns. * returns.
*/ */
void void
chopstx_exit (void *retval) chopstx_exit (void *retval)
@@ -1667,6 +1653,9 @@ chx_join_hook (struct chx_px *px, struct chx_poll_head *pd)
* *
* Canceling the timer, wake up the sleeping thread. * Canceling the timer, wake up the sleeping thread.
* No return value. * No return value.
*
* This function is DEPRECATED. Please use chopstx_cond_signal,
* where sleeping process calls chopstx_poll.
*/ */
void void
chopstx_wakeup_usec_wait (chopstx_t thd) chopstx_wakeup_usec_wait (chopstx_t thd)
@@ -1909,6 +1898,30 @@ chopstx_poll (uint32_t *usec_p, int n, ...)
return counter; return counter;
} }
/**
* chopstx_setpriority - change the schedule priority of running thread
* @prio: priority
*
* Change the schedule priority with @prio.
*
* In general, it is not recommended to use this function because
* dynamically changing schedule priorities complicates the system.
* Only a possible valid usage of this function is in the main thread
* which starts its execution with priority of CHX_PRIO_MAIN_INIT, and
* let it change its priority after initialization of other threads.
*/
void
chopstx_setpriority (chopstx_prio_t prio)
{
struct chx_thread *tp = running;
tp->prio_orig = prio;
if (prio >= CHOPSTX_PRIO_INHIBIT_PREEMPTION)
chx_cpu_sched_lock ();
tp->prio = prio;
}
/* /*
* Lower layer architecture specific exception handling entries. * Lower layer architecture specific exception handling entries.

View File

@@ -35,7 +35,6 @@ typedef uint8_t chopstx_prio_t;
extern chopstx_t chopstx_main; extern chopstx_t chopstx_main;
void chopstx_main_init (chopstx_prio_t);
/* NOTE: This signature is different to PTHREAD's one. */ /* NOTE: This signature is different to PTHREAD's one. */
chopstx_t chopstx_t
@@ -48,8 +47,6 @@ chopstx_create (uint32_t flags_and_prio,
#define CHOPSTX_PRIO_INHIBIT_PREEMPTION 248 #define CHOPSTX_PRIO_INHIBIT_PREEMPTION 248
void chopstx_usec_wait_var (uint32_t *arg);
void chopstx_usec_wait (uint32_t usec); void chopstx_usec_wait (uint32_t usec);
struct chx_spinlock { struct chx_spinlock {
@@ -117,7 +114,10 @@ void chopstx_cleanup_push (chopstx_cleanup_t *clp);
void chopstx_cleanup_pop (int execute); void chopstx_cleanup_pop (int execute);
void chopstx_wakeup_usec_wait (chopstx_t thd); void chopstx_setpriority (chopstx_prio_t);
void chopstx_usec_wait_var (uint32_t *arg); /* DEPRECATED */
void chopstx_wakeup_usec_wait (chopstx_t thd); /* DEPRECATED */
enum { enum {
CHOPSTX_POLL_COND = 0, CHOPSTX_POLL_COND = 0,
@@ -157,11 +157,6 @@ void chopstx_claim_irq (chopstx_intr_t *intr, uint8_t irq_num);
void chopstx_intr_wait (chopstx_intr_t *intr); /* DEPRECATED */ void chopstx_intr_wait (chopstx_intr_t *intr); /* DEPRECATED */
struct chx_poll_head {
uint16_t type;
uint16_t ready;
};
int chopstx_poll (uint32_t *usec_p, int n, ...); int chopstx_poll (uint32_t *usec_p, int n, ...);
#define CHOPSTX_THREAD_SIZE 64 #define CHOPSTX_THREAD_SIZE 64

View File

@@ -7,16 +7,6 @@ When it detects a coding error, this function will be called to
stop further execution of code. It never returns. stop further execution of code. It never returns.
@end deftypefun @end deftypefun
@subheading chopstx_main_init
@anchor{chopstx_main_init}
@deftypefun {void} {chopstx_main_init} (chopstx_prio_t @var{prio})
@var{prio}: priority
Initialize main thread with @var{prio}.
The thread main is created with priority CHX_PRIO_MAIN_INIT,
and it runs with that priority until this routine will is called.
@end deftypefun
@subheading chopstx_create @subheading chopstx_create
@anchor{chopstx_create} @anchor{chopstx_create}
@deftypefun {chopstx_t} {chopstx_create} (uint32_t @var{flags_and_prio}, uint32_t @var{stack_addr}, size_t @var{stack_size}, voidfunc @var{thread_entry}, void * @var{arg}) @deftypefun {chopstx_t} {chopstx_create} (uint32_t @var{flags_and_prio}, uint32_t @var{stack_addr}, size_t @var{stack_size}, voidfunc @var{thread_entry}, void * @var{arg})
@@ -40,6 +30,8 @@ Create a thread. Returns thread ID.
Sleep for micro seconds, specified by @var{var}. Sleep for micro seconds, specified by @var{var}.
Another thread can clear @var{var} to stop the caller going into sleep. Another thread can clear @var{var} to stop the caller going into sleep.
This function is DEPRECATED. Please use chopstx_poll.
@end deftypefun @end deftypefun
@subheading chopstx_usec_wait @subheading chopstx_usec_wait
@@ -150,10 +142,10 @@ clean-up will be executed.
@deftypefun {void} {chopstx_exit} (void * @var{retval}) @deftypefun {void} {chopstx_exit} (void * @var{retval})
@var{retval}: Return value (to be caught by a joining thread) @var{retval}: Return value (to be caught by a joining thread)
Calling this function terminates the execution of thread, after Calling this function terminates the execution of running thread,
calling clean up functions. If the calling thread still holds after calling clean up functions. If the calling thread still
mutexes, they will be released. If the calling thread claiming holds mutexes, they will be released. This function never
IRQ, it will be released, too. This function never returns. returns.
@end deftypefun @end deftypefun
@subheading chopstx_join @subheading chopstx_join
@@ -174,6 +166,9 @@ Returns 0 on success, 1 when waiting is interrupted.
Canceling the timer, wake up the sleeping thread. Canceling the timer, wake up the sleeping thread.
No return value. No return value.
This function is DEPRECATED. Please use chopstx_cond_signal,
where sleeping process calls chopstx_poll.
@end deftypefun @end deftypefun
@subheading chopstx_cancel @subheading chopstx_cancel
@@ -214,3 +209,17 @@ Returns old state which is 0 when it was enabled.
Returns number of active descriptors. Returns number of active descriptors.
@end deftypefun @end deftypefun
@subheading chopstx_setpriority
@anchor{chopstx_setpriority}
@deftypefun {void} {chopstx_setpriority} (chopstx_prio_t @var{prio})
@var{prio}: priority
Change the schedule priority with @var{prio}.
In general, it is not recommended to use this function because
dynamically changing schedule priorities complicates the system.
Only a possible valid usage of this function is in the main thread
which starts its execution with priority of CHX_PRIO_MAIN_INIT, and
let it change its priority after initialization of other threads.
@end deftypefun

View File

@@ -1,7 +1,7 @@
/* /*
* eventflag.c - Eventflag with/without timeout * eventflag.c - Eventflag
* *
* Copyright (C) 2013 Flying Stone Technology * Copyright (C) 2013, 2016 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Chopstx, a thread library for embedded. * This file is a part of Chopstx, a thread library for embedded.
@@ -31,23 +31,12 @@
#include <chopstx.h> #include <chopstx.h>
#include <eventflag.h> #include <eventflag.h>
enum {
EVENTFLAG_ERR_WAIT = CHOPSTX_ERR_JOIN + 1,
EVENTFLAG_ERR_TIMED_WAIT,
};
void void
eventflag_init (struct eventflag *ev, chopstx_t sleeper) eventflag_init (struct eventflag *ev)
{ {
ev->sleeper = sleeper; ev->flags = 0;
chopstx_cond_init (&ev->cond);
if (sleeper)
ev->u.wait_usec = 0;
else
chopstx_cond_init (&ev->u.cond);
ev->flag = 0;
chopstx_mutex_init (&ev->mutex); chopstx_mutex_init (&ev->mutex);
} }
@@ -57,48 +46,52 @@ eventflag_wait (struct eventflag *ev)
{ {
int n; int n;
if (ev->sleeper)
chx_fatal (EVENTFLAG_ERR_WAIT);
chopstx_mutex_lock (&ev->mutex); chopstx_mutex_lock (&ev->mutex);
if (!ev->flag) if (!ev->flags)
chopstx_cond_wait (&ev->u.cond, &ev->mutex); chopstx_cond_wait (&ev->u.cond, &ev->mutex);
n = __builtin_ffs (ev->flag); n = __builtin_ffs (ev->flags);
ev->flag &= ~(1 << (n - 1)); ev->flags &= ~(1 << (n - 1));
chopstx_mutex_unlock (&ev->mutex); chopstx_mutex_unlock (&ev->mutex);
return (1 << (n - 1)); return (1 << (n - 1));
} }
static int
eventflag_check (void *arg)
{
struct eventflag *ev = arg;
return ev->flags != 0;
}
eventmask_t eventmask_t
eventflag_wait_timeout (struct eventflag *ev, uint32_t usec) eventflag_wait_timeout (struct eventflag *ev, uint32_t usec)
{ {
eventmask_t em = 0; chopstx_poll_cond_t poll_desc;
int n; int n;
eventmask_t em = 0;
if (ev->sleeper == 0) poll_desc.type = CHOPSTX_POLL_COND;
chx_fatal (EVENTFLAG_ERR_TIMED_WAIT); poll_desc.ready = 0;
poll_desc.cond = &ev->cond;
poll_desc.mutex = &ev->mutex;
poll_desc.check = eventflag_check;
poll_desc.arg = ev;
chopstx_poll (&usec, 1, &poll_desc);
chopstx_mutex_lock (&ev->mutex); chopstx_mutex_lock (&ev->mutex);
n = __builtin_ffs (ev->flags);
if (!ev->flag)
{
ev->u.wait_usec = usec;
chopstx_mutex_unlock (&ev->mutex);
chopstx_usec_wait_var (&ev->u.wait_usec);
chopstx_mutex_lock (&ev->mutex);
ev->u.wait_usec = 0;
}
n = __builtin_ffs (ev->flag);
if (n) if (n)
{ {
em = (1 << (n - 1)); em = (1 << (n - 1));
ev->flag &= ~em; ev->flags &= ~em;
} }
chopstx_mutex_unlock (&ev->mutex); chopstx_mutex_unlock (&ev->mutex);
return em; return em;
} }
@@ -108,15 +101,6 @@ eventflag_signal (struct eventflag *ev, eventmask_t m)
{ {
chopstx_mutex_lock (&ev->mutex); chopstx_mutex_lock (&ev->mutex);
ev->flag |= m; ev->flag |= m;
if (ev->sleeper)
{
if (ev->u.wait_usec)
{
ev->u.wait_usec = 0;
chopstx_wakeup_usec_wait (ev->sleeper);
}
}
else
chopstx_cond_signal (&ev->u.cond); chopstx_cond_signal (&ev->u.cond);
chopstx_mutex_unlock (&ev->mutex); chopstx_mutex_unlock (&ev->mutex);
} }

View File

@@ -1,16 +1,12 @@
typedef uint32_t eventmask_t; typedef uint32_t eventmask_t;
struct eventflag { struct eventflag {
chopstx_t sleeper; eventmask_t flags;
eventmask_t flag;
chopstx_mutex_t mutex; chopstx_mutex_t mutex;
union {
uint32_t wait_usec;
chopstx_cond_t cond; chopstx_cond_t cond;
} u;
}; };
void eventflag_init (struct eventflag *ev, chopstx_t owner); void eventflag_init (struct eventflag *ev);
eventmask_t eventflag_wait (struct eventflag *ev); eventmask_t eventflag_wait (struct eventflag *ev);
eventmask_t eventflag_wait_timeout (struct eventflag *ev, uint32_t usec); eventmask_t eventflag_wait_timeout (struct eventflag *ev, uint32_t usec);
void eventflag_signal (struct eventflag *ev, eventmask_t m); void eventflag_signal (struct eventflag *ev, eventmask_t m);