summaryrefslogtreecommitdiff
path: root/components/drivers/src
diff options
context:
space:
mode:
authorsheltonyu <[email protected]>2021-04-13 11:37:46 +0800
committerGitHub <[email protected]>2021-04-13 11:37:46 +0800
commit46c5ba9225702bf473646ec2f4200c9560e2db90 (patch)
treea7fe59ac9ce9a6a1c90d9c81324a4a6bb91b38a4 /components/drivers/src
parent35ef1f9e0fcf1ae881a83558dbf7334ab08c598e (diff)
parentc44e5165bef5b7b069eb99a4f027454f417a726b (diff)
Merge branch 'master' into developer
Diffstat (limited to 'components/drivers/src')
-rw-r--r--components/drivers/src/completion.c2
-rw-r--r--components/drivers/src/dataqueue.c28
-rw-r--r--components/drivers/src/pipe.c22
-rw-r--r--components/drivers/src/ringblk_buf.c44
-rw-r--r--components/drivers/src/ringbuffer.c12
-rw-r--r--components/drivers/src/waitqueue.c6
-rw-r--r--components/drivers/src/workqueue.c291
7 files changed, 175 insertions, 230 deletions
diff --git a/components/drivers/src/completion.c b/components/drivers/src/completion.c
index 9e461e49ce..b91ae3d6dc 100644
--- a/components/drivers/src/completion.c
+++ b/components/drivers/src/completion.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
diff --git a/components/drivers/src/dataqueue.c b/components/drivers/src/dataqueue.c
index 1651417bb9..f32efa1849 100644
--- a/components/drivers/src/dataqueue.c
+++ b/components/drivers/src/dataqueue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -62,7 +62,7 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
rt_ubase_t level;
rt_thread_t thread;
rt_err_t result;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -85,7 +85,7 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
/* reset thread error number */
thread->error = RT_EOK;
-
+
/* suspend thread on the push list */
rt_thread_suspend(thread);
rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
@@ -155,13 +155,13 @@ RTM_EXPORT(rt_data_queue_push);
rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
const void** data_ptr,
- rt_size_t *size,
+ rt_size_t *size,
rt_int32_t timeout)
{
rt_ubase_t level;
rt_thread_t thread;
rt_err_t result;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
RT_ASSERT(data_ptr != RT_NULL);
@@ -185,7 +185,7 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
/* reset thread error number */
thread->error = RT_EOK;
-
+
/* suspend thread on the pop list */
rt_thread_suspend(thread);
rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist));
@@ -269,11 +269,11 @@ rt_err_t rt_data_queue_peek(struct rt_data_queue *queue,
rt_size_t *size)
{
rt_ubase_t level;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
- if (queue->is_empty)
+ if (queue->is_empty)
{
return -RT_EEMPTY;
}
@@ -293,7 +293,7 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
{
rt_ubase_t level;
struct rt_thread *thread;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -303,9 +303,9 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
queue->put_index = 0;
queue->is_empty = 1;
queue->is_full = 0;
-
+
rt_hw_interrupt_enable(level);
-
+
rt_enter_critical();
/* wakeup all suspend threads */
@@ -375,7 +375,7 @@ rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue)
level = rt_hw_interrupt_disable();
queue->magic = 0;
rt_hw_interrupt_enable(level);
-
+
rt_free(queue->queue);
return RT_EOK;
@@ -386,7 +386,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
{
rt_ubase_t level;
rt_int16_t len;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -405,7 +405,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
{
len = queue->size + queue->put_index - queue->get_index;
}
-
+
rt_hw_interrupt_enable(level);
return len;
diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c
index bd392cba2b..236c1ffec7 100644
--- a/components/drivers/src/pipe.c
+++ b/components/drivers/src/pipe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -320,7 +320,7 @@ static const struct dfs_file_ops pipe_fops =
};
#endif /* end of RT_USING_POSIX */
-rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag)
+rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag)
{
rt_pipe_t *pipe = (rt_pipe_t *)device;
rt_err_t ret = RT_EOK;
@@ -330,7 +330,7 @@ rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag)
ret = -RT_EINVAL;
goto __exit;
}
-
+
rt_mutex_take(&(pipe->lock), RT_WAITING_FOREVER);
if (pipe->fifo == RT_NULL)
@@ -348,7 +348,7 @@ __exit:
return ret;
}
-rt_err_t rt_pipe_close (rt_device_t device)
+rt_err_t rt_pipe_close(rt_device_t device)
{
rt_pipe_t *pipe = (rt_pipe_t *)device;
@@ -366,7 +366,7 @@ rt_err_t rt_pipe_close (rt_device_t device)
return RT_EOK;
}
-rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
+rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
{
uint8_t *pbuf;
rt_size_t read_bytes = 0;
@@ -394,7 +394,7 @@ rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_siz
return read_bytes;
}
-rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
+rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
{
uint8_t *pbuf;
rt_size_t write_bytes = 0;
@@ -428,7 +428,7 @@ rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
}
#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops pipe_ops =
+const static struct rt_device_ops pipe_ops =
{
RT_NULL,
rt_pipe_open,
@@ -507,7 +507,7 @@ int rt_pipe_delete(const char *name)
rt_device_unregister(device);
/* close fifo ringbuffer */
- if (pipe->fifo)
+ if (pipe->fifo)
{
rt_ringbuffer_destroy(pipe->fifo);
pipe->fifo = RT_NULL;
@@ -531,8 +531,8 @@ int rt_pipe_delete(const char *name)
int pipe(int fildes[2])
{
rt_pipe_t *pipe;
- char dname[8];
- char dev_name[32];
+ char dname[RT_NAME_MAX];
+ char dev_name[RT_NAME_MAX * 4];
static int pipeno = 0;
rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno++);
@@ -564,7 +564,7 @@ int pipe(int fildes[2])
int mkfifo(const char *path, mode_t mode)
{
rt_pipe_t *pipe;
-
+
pipe = rt_pipe_create(path, PIPE_BUFSZ);
if (pipe == RT_NULL)
{
diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c
index 7d83149c5e..c6688b3d2b 100644
--- a/components/drivers/src/ringblk_buf.c
+++ b/components/drivers/src/ringblk_buf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -50,26 +50,26 @@ RTM_EXPORT(rt_rbb_init);
* @param buf_size buffer size
* @param blk_max_num max block number
*
- * @return != NULL: ring block buffer object
- * NULL: create failed
+ * @return != RT_NULL: ring block buffer object
+ * RT_NULL: create failed
*/
rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num)
{
- rt_rbb_t rbb = NULL;
+ rt_rbb_t rbb = RT_NULL;
rt_uint8_t *buf;
rt_rbb_blk_t blk_set;
rbb = (rt_rbb_t)rt_malloc(sizeof(struct rt_rbb));
if (!rbb)
{
- return NULL;
+ return RT_NULL;
}
buf = (rt_uint8_t *)rt_malloc(buf_size);
if (!buf)
{
rt_free(rbb);
- return NULL;
+ return RT_NULL;
}
blk_set = (rt_rbb_blk_t)rt_malloc(sizeof(struct rt_rbb_blk) * blk_max_num);
@@ -77,7 +77,7 @@ rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num)
{
rt_free(buf);
rt_free(rbb);
- return NULL;
+ return RT_NULL;
}
rt_rbb_init(rbb, buf, buf_size, blk_set, blk_max_num);
@@ -116,7 +116,7 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb)
}
}
- return NULL;
+ return RT_NULL;
}
/**
@@ -127,14 +127,14 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb)
*
* @note When your application need align access, please make the blk_szie is aligned.
*
- * @return != NULL: allocated block
- * NULL: allocate failed
+ * @return != RT_NULL: allocated block
+ * RT_NULL: allocate failed
*/
rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
{
rt_base_t level;
rt_size_t empty1 = 0, empty2 = 0;
- rt_rbb_blk_t head, tail, new_rbb = NULL;
+ rt_rbb_blk_t head, tail, new_rbb = RT_NULL;
RT_ASSERT(rbb);
RT_ASSERT(blk_size < (1L << 24));
@@ -178,7 +178,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
else
{
/* no space */
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
}
else
@@ -202,7 +202,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
else
{
/* no space */
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
}
}
@@ -217,7 +217,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
}
else
{
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
rt_hw_interrupt_enable(level);
@@ -245,13 +245,13 @@ RTM_EXPORT(rt_rbb_blk_put);
*
* @param rbb ring block buffer object
*
- * @return != NULL: block
- * NULL: get failed
+ * @return != RT_NULL: block
+ * RT_NULL: get failed
*/
rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb)
{
rt_base_t level;
- rt_rbb_blk_t block = NULL;
+ rt_rbb_blk_t block = RT_NULL;
rt_slist_t *node;
RT_ASSERT(rbb);
@@ -271,7 +271,7 @@ rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb)
}
}
/* not found */
- block = NULL;
+ block = RT_NULL;
__exit:
@@ -364,7 +364,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl
rt_base_t level;
rt_size_t data_total_size = 0;
rt_slist_t *node;
- rt_rbb_blk_t last_block = NULL, block;
+ rt_rbb_blk_t last_block = RT_NULL, block;
RT_ASSERT(rbb);
RT_ASSERT(blk_queue);
@@ -388,7 +388,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl
else
{
/* the first block must be put status */
- last_block = NULL;
+ last_block = RT_NULL;
continue;
}
}
@@ -493,7 +493,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb)
rt_base_t level;
rt_size_t data_len = 0;
rt_slist_t *node;
- rt_rbb_blk_t last_block = NULL, block;
+ rt_rbb_blk_t last_block = RT_NULL, block;
RT_ASSERT(rbb);
@@ -510,7 +510,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb)
if (last_block->status != RT_RBB_BLK_PUT)
{
/* the first block must be put status */
- last_block = NULL;
+ last_block = RT_NULL;
continue;
}
}
diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c
index 88afd19506..29de20b087 100644
--- a/components/drivers/src/ringbuffer.c
+++ b/components/drivers/src/ringbuffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -320,8 +320,8 @@ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
}
RTM_EXPORT(rt_ringbuffer_getchar);
-/**
- * get the size of data in rb
+/**
+ * get the size of data in rb
*/
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
{
@@ -341,8 +341,8 @@ rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
}
RTM_EXPORT(rt_ringbuffer_data_len);
-/**
- * empty the rb
+/**
+ * empty the rb
*/
void rt_ringbuffer_reset(struct rt_ringbuffer *rb)
{
@@ -362,7 +362,7 @@ struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size)
struct rt_ringbuffer *rb;
rt_uint8_t *pool;
- RT_ASSERT(size > 0);
+ RT_ASSERT(size > 0);
size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
diff --git a/components/drivers/src/waitqueue.c b/components/drivers/src/waitqueue.c
index 02240edbdf..7fe75a51ba 100644
--- a/components/drivers/src/waitqueue.c
+++ b/components/drivers/src/waitqueue.c
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
- * 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon
+ * 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon
* to blocked thread.
*/
@@ -121,7 +121,7 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
level = rt_hw_interrupt_disable();
__exit_wakeup:
- queue->flag = 0;
+ queue->flag = RT_WQ_FLAG_CLEAN;
rt_hw_interrupt_enable(level);
rt_wqueue_remove(&__wait);
diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c
index 2b5630d8d0..f195dad927 100644
--- a/components/drivers/src/workqueue.c
+++ b/components/drivers/src/workqueue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -58,15 +58,17 @@ static void _workqueue_thread_entry(void *parameter)
while (1)
{
+ level = rt_hw_interrupt_disable();
if (rt_list_isempty(&(queue->work_list)))
{
/* no software timer exist, suspend self. */
rt_thread_suspend(rt_thread_self());
+ rt_hw_interrupt_enable(level);
rt_schedule();
+ continue;
}
/* we have work to do with. */
- level = rt_hw_interrupt_disable();
work = rt_list_entry(queue->work_list.next, struct rt_work, list);
rt_list_remove(&(work->list));
queue->work_current = work;
@@ -76,175 +78,134 @@ static void _workqueue_thread_entry(void *parameter)
/* do work */
work->work_func(work, work->work_data);
- level = rt_hw_interrupt_disable();
/* clean current work */
queue->work_current = RT_NULL;
- rt_hw_interrupt_enable(level);
/* ack work completion */
_workqueue_work_completion(queue);
}
}
-static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work)
+static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue,
+ struct rt_work *work, rt_tick_t ticks)
{
rt_base_t level;
+ rt_err_t err;
level = rt_hw_interrupt_disable();
- if (work->flags & RT_WORK_STATE_PENDING)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
- /* NOTE: the work MUST be initialized firstly */
+ /* remove list */
rt_list_remove(&(work->list));
-
- rt_list_insert_after(queue->work_list.prev, &(work->list));
- work->flags |= RT_WORK_STATE_PENDING;
-
- /* whether the workqueue is doing work */
- if (queue->work_current == RT_NULL)
+ work->flags &= ~RT_WORK_STATE_PENDING;
+ /* */
+ if (ticks == 0)
{
- rt_hw_interrupt_enable(level);
- /* resume work thread */
- rt_thread_resume(queue->work_thread);
- rt_schedule();
+ if (queue->work_current != work)
+ {
+ rt_list_insert_after(queue->work_list.prev, &(work->list));
+ work->flags |= RT_WORK_STATE_PENDING;
+ work->workqueue = queue;
+ err = RT_EOK;
+ }
+ else
+ {
+ err = -RT_EBUSY;
+ }
+
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
+ {
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
+ rt_schedule();
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+ return err;
}
- else
+ else if (ticks < RT_TICK_MAX / 2)
{
+ /* Timer started */
+ if (work->flags & RT_WORK_STATE_SUBMITTING)
+ {
+ rt_timer_stop(&work->timer);
+ rt_timer_control(&work->timer, RT_TIMER_CTRL_SET_TIME, &ticks);
+ }
+ else
+ {
+ rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler,
+ work, ticks, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
+ work->flags |= RT_WORK_STATE_SUBMITTING;
+ }
+ work->workqueue = queue;
+ /* insert delay work list */
+ rt_list_insert_after(queue->delayed_list.prev, &(work->list));
rt_hw_interrupt_enable(level);
+ rt_timer_start(&(work->timer));
+ return RT_EOK;
}
-
- return RT_EOK;
+ rt_hw_interrupt_enable(level);
+ return -RT_ERROR;
}
static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work)
{
rt_base_t level;
+ rt_err_t err;
level = rt_hw_interrupt_disable();
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
rt_list_remove(&(work->list));
work->flags &= ~RT_WORK_STATE_PENDING;
- rt_hw_interrupt_enable(level);
-
- return RT_EOK;
-}
-
-static rt_err_t _workqueue_cancel_delayed_work(struct rt_work *work)
-{
- rt_base_t level;
- int ret = RT_EOK;
-
- if (!work->workqueue)
- {
- ret = -EINVAL;
- goto __exit;
- }
-
- if (work->flags & RT_WORK_STATE_PENDING)
- {
- /* Remove from the queue if already submitted */
- ret = _workqueue_cancel_work(work->workqueue, work);
- if (ret)
- {
- goto __exit;
- }
- }
- else
+ /* Timer started */
+ if (work->flags & RT_WORK_STATE_SUBMITTING)
{
- if (work->flags & RT_WORK_STATE_SUBMITTING)
- {
- level = rt_hw_interrupt_disable();
- rt_timer_stop(&(work->timer));
- rt_timer_detach(&(work->timer));
- work->flags &= ~RT_WORK_STATE_SUBMITTING;
- rt_hw_interrupt_enable(level);
- }
+ rt_timer_stop(&(work->timer));
+ rt_timer_detach(&(work->timer));
+ work->flags &= ~RT_WORK_STATE_SUBMITTING;
}
-
- level = rt_hw_interrupt_disable();
- /* Detach from workqueue */
+ err = queue->work_current != work ? RT_EOK : -RT_EBUSY;
work->workqueue = RT_NULL;
- work->flags &= ~(RT_WORK_STATE_PENDING);
rt_hw_interrupt_enable(level);
-
-__exit:
- return ret;
+ return err;
}
-static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue,
- struct rt_work *work, rt_tick_t ticks)
+static void _delayed_work_timeout_handler(void *parameter)
{
+ struct rt_work *work;
+ struct rt_workqueue *queue;
rt_base_t level;
- rt_err_t ret = RT_EOK;
- /* Work cannot be active in multiple queues */
- if (work->workqueue && work->workqueue != queue)
- {
- ret = -RT_EINVAL;
- goto __exit;
- }
+ work = (struct rt_work *)parameter;
+ queue = work->workqueue;
+ RT_ASSERT(queue != RT_NULL);
- /* Cancel if work has been submitted */
- if (work->workqueue == queue)
+ level = rt_hw_interrupt_disable();
+ rt_timer_detach(&(work->timer));
+ work->flags &= ~RT_WORK_STATE_SUBMITTING;
+ /* remove delay list */
+ rt_list_remove(&(work->list));
+ /* insert work queue */
+ if (queue->work_current != work)
{
- ret = _workqueue_cancel_delayed_work(work);
- if (ret < 0)
- {
- goto __exit;
- }
+ rt_list_insert_after(queue->work_list.prev, &(work->list));
+ work->flags |= RT_WORK_STATE_PENDING;
}
-
- level = rt_hw_interrupt_disable();
- /* Attach workqueue so the timeout callback can submit it */
- work->workqueue = queue;
- rt_hw_interrupt_enable(level);
-
- if (!ticks)
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
- /* Submit work if no ticks is 0 */
- ret = _workqueue_submit_work(work->workqueue, work);
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
+ rt_schedule();
}
else
{
- level = rt_hw_interrupt_disable();
- /* Add timeout */
- work->flags |= RT_WORK_STATE_SUBMITTING;
- rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, work, ticks,
- RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
rt_hw_interrupt_enable(level);
- rt_timer_start(&(work->timer));
}
-
-__exit:
- return ret;
-}
-
-static void _delayed_work_timeout_handler(void *parameter)
-{
- struct rt_work *delayed_work;
- rt_base_t level;
-
- delayed_work = (struct rt_work *)parameter;
- level = rt_hw_interrupt_disable();
- rt_timer_stop(&(delayed_work->timer));
- rt_timer_detach(&(delayed_work->timer));
- delayed_work->flags &= ~RT_WORK_STATE_SUBMITTING;
- delayed_work->type &= ~RT_WORK_TYPE_DELAYED;
- rt_hw_interrupt_enable(level);
- _workqueue_submit_work(delayed_work->workqueue, delayed_work);
}
struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority)
@@ -256,6 +217,7 @@ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_siz
{
/* initialize work list */
rt_list_init(&(queue->work_list));
+ rt_list_init(&(queue->delayed_list));
queue->work_current = RT_NULL;
rt_sem_init(&(queue->sem), "wqueue", 0, RT_IPC_FLAG_FIFO);
@@ -277,7 +239,9 @@ rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue)
{
RT_ASSERT(queue != RT_NULL);
+ rt_workqueue_cancel_all_work(queue);
rt_thread_delete(queue->work_thread);
+ rt_sem_detach(&(queue->sem));
RT_KERNEL_FREE(queue);
return RT_EOK;
@@ -288,7 +252,7 @@ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work)
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- return _workqueue_submit_work(queue, work);
+ return _workqueue_submit_work(queue, work, 0);
}
rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time)
@@ -296,19 +260,7 @@ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *wo
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- if (time > 0)
- {
- work->type |= RT_WORK_TYPE_DELAYED;
- }
-
- if (work->type & RT_WORK_TYPE_DELAYED)
- {
- return _workqueue_submit_delayed_work(queue, work, time);
- }
- else
- {
- return _workqueue_submit_work(queue, work);
- }
+ return _workqueue_submit_work(queue, work, time);
}
rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work)
@@ -318,51 +270,38 @@ rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *
RT_ASSERT(work != RT_NULL);
level = rt_hw_interrupt_disable();
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
/* NOTE: the work MUST be initialized firstly */
rt_list_remove(&(work->list));
-
- rt_list_insert_after(queue->work_list.prev, &(work->list));
- if (queue->work_current == RT_NULL)
+ rt_list_insert_after(&queue->work_list, &(work->list));
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
- rt_hw_interrupt_enable(level);
/* resume work thread */
rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
rt_schedule();
}
- else rt_hw_interrupt_enable(level);
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
return RT_EOK;
}
rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work)
{
- RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
-
- if (work->type & RT_WORK_TYPE_DELAYED)
- {
- return _workqueue_cancel_delayed_work(work);
- }
- else
- {
- return _workqueue_cancel_work(queue, work);
- }
+ RT_ASSERT(queue != RT_NULL);
+ return _workqueue_cancel_work(queue, work);
}
rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work)
{
- rt_base_t level;
-
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- level = rt_hw_interrupt_disable();
if (queue->work_current == work) /* it's current work in the queue */
{
/* wait for work completion */
@@ -370,24 +309,30 @@ rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_wor
}
else
{
- rt_list_remove(&(work->list));
+ _workqueue_cancel_work(queue, work);
}
- work->flags &= ~RT_WORK_STATE_PENDING;
- rt_hw_interrupt_enable(level);
return RT_EOK;
}
rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue)
{
- struct rt_list_node *node, *next;
+ struct rt_work *work;
+
RT_ASSERT(queue != RT_NULL);
+ /* cancel work */
rt_enter_critical();
- for (node = queue->work_list.next; node != &(queue->work_list); node = next)
+ while (rt_list_isempty(&queue->work_list) == RT_FALSE)
+ {
+ work = rt_list_first_entry(&queue->work_list, struct rt_work, list);
+ _workqueue_cancel_work(queue, work);
+ }
+ /* cancel delay work */
+ while (rt_list_isempty(&queue->delayed_list) == RT_FALSE)
{
- next = node->next;
- rt_list_remove(node);
+ work = rt_list_first_entry(&queue->delayed_list, struct rt_work, list);
+ _workqueue_cancel_work(queue, work);
}
rt_exit_critical();
@@ -416,14 +361,14 @@ rt_err_t rt_work_cancel(struct rt_work *work)
int rt_work_sys_workqueue_init(void)
{
if (sys_workq != RT_NULL)
- return 0;
+ return RT_EOK;
sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE,
RT_SYSTEM_WORKQUEUE_PRIORITY);
+ RT_ASSERT(sys_workq != RT_NULL);
return RT_EOK;
}
-
INIT_PREV_EXPORT(rt_work_sys_workqueue_init);
#endif
#endif