summaryrefslogtreecommitdiff
path: root/components/drivers/src
diff options
context:
space:
mode:
authoryangjie11 <[email protected]>2020-11-18 09:56:35 +0800
committerGitHub <[email protected]>2020-11-18 09:56:35 +0800
commitd4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch)
tree4773b40cb012475c5daf74bfd55707e141477669 /components/drivers/src
parent2b98f4720c827ae1850df78299f6b273d568c8c7 (diff)
parent2ef3c9d861f55253620996a94831a4be31ca6620 (diff)
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'components/drivers/src')
-rw-r--r--components/drivers/src/dataqueue.c131
-rw-r--r--components/drivers/src/pipe.c37
-rw-r--r--components/drivers/src/ringblk_buf.c48
-rw-r--r--components/drivers/src/ringbuffer.c5
-rw-r--r--components/drivers/src/workqueue.c280
5 files changed, 404 insertions, 97 deletions
diff --git a/components/drivers/src/dataqueue.c b/components/drivers/src/dataqueue.c
index 7553986b9f..bfe8e12573 100644
--- a/components/drivers/src/dataqueue.c
+++ b/components/drivers/src/dataqueue.c
@@ -13,6 +13,8 @@
#include <rtdevice.h>
#include <rthw.h>
+#define DATAQUEUE_MAGIC 0xbead0e0e
+
struct rt_data_item
{
const void *data_ptr;
@@ -26,14 +28,18 @@ rt_data_queue_init(struct rt_data_queue *queue,
void (*evt_notify)(struct rt_data_queue *queue, rt_uint32_t event))
{
RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(size > 0);
queue->evt_notify = evt_notify;
+ queue->magic = DATAQUEUE_MAGIC;
queue->size = size;
queue->lwm = lwm;
queue->get_index = 0;
queue->put_index = 0;
+ queue->is_empty = 1;
+ queue->is_full = 0;
rt_list_init(&(queue->suspended_push_list));
rt_list_init(&(queue->suspended_pop_list));
@@ -58,12 +64,13 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
rt_err_t result;
RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
result = RT_EOK;
thread = rt_thread_self();
level = rt_hw_interrupt_disable();
- while (queue->put_index - queue->get_index == queue->size)
+ while (queue->is_full)
{
/* queue is full */
if (timeout == 0)
@@ -104,9 +111,18 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
if (result != RT_EOK) goto __exit;
}
- queue->queue[queue->put_index % queue->size].data_ptr = data_ptr;
- queue->queue[queue->put_index % queue->size].data_size = data_size;
+ queue->queue[queue->put_index].data_ptr = data_ptr;
+ queue->queue[queue->put_index].data_size = data_size;
queue->put_index += 1;
+ if (queue->put_index == queue->size)
+ {
+ queue->put_index = 0;
+ }
+ queue->is_empty = 0;
+ if (queue->put_index == queue->get_index)
+ {
+ queue->is_full = 1;
+ }
/* there is at least one thread in suspended list */
if (!rt_list_isempty(&(queue->suspended_pop_list)))
@@ -145,8 +161,9 @@ rt_err_t rt_data_queue_pop(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);
RT_ASSERT(data_ptr != RT_NULL);
RT_ASSERT(size != RT_NULL);
@@ -154,7 +171,7 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
thread = rt_thread_self();
level = rt_hw_interrupt_disable();
- while (queue->get_index == queue->put_index)
+ while (queue->is_empty)
{
/* queue is empty */
if (timeout == 0)
@@ -195,12 +212,20 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
goto __exit;
}
- *data_ptr = queue->queue[queue->get_index % queue->size].data_ptr;
- *size = queue->queue[queue->get_index % queue->size].data_size;
-
+ *data_ptr = queue->queue[queue->get_index].data_ptr;
+ *size = queue->queue[queue->get_index].data_size;
queue->get_index += 1;
+ if (queue->get_index == queue->size)
+ {
+ queue->get_index = 0;
+ }
+ queue->is_full = 0;
+ if (queue->put_index == queue->get_index)
+ {
+ queue->is_empty = 1;
+ }
- if ((queue->put_index - queue->get_index) <= queue->lwm)
+ if (rt_data_queue_len(queue) <= queue->lwm)
{
/* there is at least one thread in suspended list */
if (!rt_list_isempty(&(queue->suspended_push_list)))
@@ -244,20 +269,19 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue,
rt_size_t *size)
{
rt_ubase_t level;
-
+
RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
- level = rt_hw_interrupt_disable();
-
- if (queue->get_index == queue->put_index)
+ if (queue->is_empty)
{
- rt_hw_interrupt_enable(level);
-
return -RT_EEMPTY;
}
- *data_ptr = queue->queue[queue->get_index % queue->size].data_ptr;
- *size = queue->queue[queue->get_index % queue->size].data_size;
+ level = rt_hw_interrupt_disable();
+
+ *data_ptr = queue->queue[queue->get_index].data_ptr;
+ *size = queue->queue[queue->get_index].data_size;
rt_hw_interrupt_enable(level);
@@ -267,9 +291,21 @@ RTM_EXPORT(rt_data_queue_peak);
void rt_data_queue_reset(struct rt_data_queue *queue)
{
+ rt_ubase_t level;
struct rt_thread *thread;
- register rt_ubase_t temp;
+
+ RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
+
+ level = rt_hw_interrupt_disable();
+ queue->get_index = 0;
+ queue->put_index = 0;
+ queue->is_empty = 1;
+ queue->is_full = 0;
+
+ rt_hw_interrupt_enable(level);
+
rt_enter_critical();
/* wakeup all suspend threads */
@@ -277,7 +313,7 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
while (!rt_list_isempty(&(queue->suspended_pop_list)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(queue->suspended_pop_list.next,
@@ -294,14 +330,14 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
rt_thread_resume(thread);
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
/* resume on push list */
while (!rt_list_isempty(&(queue->suspended_push_list)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(queue->suspended_push_list.next,
@@ -318,10 +354,61 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
rt_thread_resume(thread);
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
rt_exit_critical();
rt_schedule();
}
RTM_EXPORT(rt_data_queue_reset);
+
+rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue)
+{
+ rt_ubase_t level;
+
+ RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
+
+ /* wakeup all suspend threads */
+ rt_data_queue_reset(queue);
+
+ level = rt_hw_interrupt_disable();
+ queue->magic = 0;
+ rt_hw_interrupt_enable(level);
+
+ rt_free(queue->queue);
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_data_queue_deinit);
+
+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);
+
+ if (queue->is_empty)
+ {
+ return 0;
+ }
+
+ level = rt_hw_interrupt_disable();
+
+ if (queue->put_index > queue->get_index)
+ {
+ len = queue->put_index - queue->get_index;
+ }
+ else
+ {
+ len = queue->size + queue->put_index - queue->get_index;
+ }
+
+ rt_hw_interrupt_enable(level);
+
+ return len;
+}
+RTM_EXPORT(rt_data_queue_len);
+
diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c
index 065fd21dc1..2a7e143f6c 100644
--- a/components/drivers/src/pipe.c
+++ b/components/drivers/src/pipe.c
@@ -19,6 +19,7 @@
static int pipe_fops_open(struct dfs_fd *fd)
{
+ int rc = 0;
rt_device_t device;
rt_pipe_t *pipe;
@@ -31,6 +32,11 @@ static int pipe_fops_open(struct dfs_fd *fd)
if (device->ref_count == 0)
{
pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
+ if (pipe->fifo == RT_NULL)
+ {
+ rc = -RT_ENOMEM;
+ goto __exit;
+ }
}
switch (fd->flags & O_ACCMODE)
@@ -48,9 +54,10 @@ static int pipe_fops_open(struct dfs_fd *fd)
}
device->ref_count ++;
+__exit:
rt_mutex_release(&(pipe->lock));
- return 0;
+ return rc;
}
static int pipe_fops_close(struct dfs_fd *fd)
@@ -90,13 +97,20 @@ static int pipe_fops_close(struct dfs_fd *fd)
if (device->ref_count == 1)
{
- rt_ringbuffer_destroy(pipe->fifo);
+ if (pipe->fifo != RT_NULL)
+ rt_ringbuffer_destroy(pipe->fifo);
pipe->fifo = RT_NULL;
}
device->ref_count --;
rt_mutex_release(&(pipe->lock));
+ if (device->ref_count == 0 && pipe->is_named == RT_FALSE)
+ {
+ /* delete the unamed pipe */
+ rt_pipe_delete(device->parent.name);
+ }
+
return 0;
}
@@ -309,18 +323,29 @@ static const struct dfs_file_ops pipe_fops =
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;
- if (device == RT_NULL) return -RT_EINVAL;
+ if (device == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ goto __exit;
+ }
+
rt_mutex_take(&(pipe->lock), RT_WAITING_FOREVER);
if (pipe->fifo == RT_NULL)
{
pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
+ if (pipe->fifo == RT_NULL)
+ {
+ ret = -RT_ENOMEM;
+ }
}
rt_mutex_release(&(pipe->lock));
- return RT_EOK;
+__exit:
+ return ret;
}
rt_err_t rt_pipe_close (rt_device_t device)
@@ -419,10 +444,11 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
rt_pipe_t *pipe;
rt_device_t dev;
- pipe = rt_malloc(sizeof(rt_pipe_t));
+ pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t));
if (pipe == RT_NULL) return RT_NULL;
rt_memset(pipe, 0, sizeof(rt_pipe_t));
+ pipe->is_named = RT_TRUE; /* initialize as a named pipe */
rt_mutex_init(&(pipe->lock), name, RT_IPC_FLAG_FIFO);
rt_wqueue_init(&(pipe->reader_queue));
rt_wqueue_init(&(pipe->writer_queue));
@@ -517,6 +543,7 @@ int pipe(int fildes[2])
return -1;
}
+ pipe->is_named = RT_FALSE; /* unamed pipe */
rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
fildes[0] = open(dev_name, O_RDONLY, 0);
if (fildes[0] < 0)
diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c
index 74ced674fe..7d83149c5e 100644
--- a/components/drivers/src/ringblk_buf.c
+++ b/components/drivers/src/ringblk_buf.c
@@ -95,9 +95,9 @@ void rt_rbb_destroy(rt_rbb_t rbb)
{
RT_ASSERT(rbb);
- rt_free(rbb);
rt_free(rbb->buf);
rt_free(rbb->blk_set);
+ rt_free(rbb);
}
RTM_EXPORT(rt_rbb_destroy);
@@ -134,16 +134,16 @@ 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 = NULL;
+ rt_rbb_blk_t head, tail, new_rbb = NULL;
RT_ASSERT(rbb);
RT_ASSERT(blk_size < (1L << 24));
level = rt_hw_interrupt_disable();
- new = find_empty_blk_in_set(rbb);
+ new_rbb = find_empty_blk_in_set(rbb);
- if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new)
+ if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new_rbb)
{
if (rt_slist_len(&rbb->blk_list) > 0)
{
@@ -163,22 +163,22 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
if (empty1 >= blk_size)
{
- rt_slist_append(&rbb->blk_list, &new->list);
- new->status = RT_RBB_BLK_INITED;
- new->buf = tail->buf + tail->size;
- new->size = blk_size;
+ rt_slist_append(&rbb->blk_list, &new_rbb->list);
+ new_rbb->status = RT_RBB_BLK_INITED;
+ new_rbb->buf = tail->buf + tail->size;
+ new_rbb->size = blk_size;
}
else if (empty2 >= blk_size)
{
- rt_slist_append(&rbb->blk_list, &new->list);
- new->status = RT_RBB_BLK_INITED;
- new->buf = rbb->buf;
- new->size = blk_size;
+ rt_slist_append(&rbb->blk_list, &new_rbb->list);
+ new_rbb->status = RT_RBB_BLK_INITED;
+ new_rbb->buf = rbb->buf;
+ new_rbb->size = blk_size;
}
else
{
/* no space */
- new = NULL;
+ new_rbb = NULL;
}
}
else
@@ -194,35 +194,35 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
if (empty1 >= blk_size)
{
- rt_slist_append(&rbb->blk_list, &new->list);
- new->status = RT_RBB_BLK_INITED;
- new->buf = tail->buf + tail->size;
- new->size = blk_size;
+ rt_slist_append(&rbb->blk_list, &new_rbb->list);
+ new_rbb->status = RT_RBB_BLK_INITED;
+ new_rbb->buf = tail->buf + tail->size;
+ new_rbb->size = blk_size;
}
else
{
/* no space */
- new = NULL;
+ new_rbb = NULL;
}
}
}
else
{
/* the list is empty */
- rt_slist_append(&rbb->blk_list, &new->list);
- new->status = RT_RBB_BLK_INITED;
- new->buf = rbb->buf;
- new->size = blk_size;
+ rt_slist_append(&rbb->blk_list, &new_rbb->list);
+ new_rbb->status = RT_RBB_BLK_INITED;
+ new_rbb->buf = rbb->buf;
+ new_rbb->size = blk_size;
}
}
else
{
- new = NULL;
+ new_rbb = NULL;
}
rt_hw_interrupt_enable(level);
- return new;
+ return new_rbb;
}
RTM_EXPORT(rt_rbb_blk_alloc);
diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c
index 2e078ae053..c6a491a7cc 100644
--- a/components/drivers/src/ringbuffer.c
+++ b/components/drivers/src/ringbuffer.c
@@ -332,14 +332,15 @@ struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size)
size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
- rb = rt_malloc(sizeof(struct rt_ringbuffer));
+ rb = (struct rt_ringbuffer *)rt_malloc(sizeof(struct rt_ringbuffer));
if (rb == RT_NULL)
goto exit;
- pool = rt_malloc(size);
+ pool = (rt_uint8_t *)rt_malloc(size);
if (pool == RT_NULL)
{
rt_free(rb);
+ rb = RT_NULL;
goto exit;
}
rt_ringbuffer_init(rb, pool, size);
diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c
index 158ea8b69b..2e0280df3a 100644
--- a/components/drivers/src/workqueue.c
+++ b/components/drivers/src/workqueue.c
@@ -13,11 +13,14 @@
#include <rtdevice.h>
#ifdef RT_USING_HEAP
+
+static void _delayed_work_timeout_handler(void *parameter);
+
rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue)
{
rt_err_t result;
-
- rt_enter_critical();
+
+ rt_enter_critical();
while (1)
{
/* try to take condition semaphore */
@@ -40,17 +43,17 @@ rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue)
}
}
rt_exit_critical();
-
+
return result;
}
-static void _workqueue_thread_entry(void* parameter)
+static void _workqueue_thread_entry(void *parameter)
{
rt_base_t level;
- struct rt_work* work;
- struct rt_workqueue* queue;
+ struct rt_work *work;
+ struct rt_workqueue *queue;
- queue = (struct rt_workqueue*) parameter;
+ queue = (struct rt_workqueue *) parameter;
RT_ASSERT(queue != RT_NULL);
while (1)
@@ -67,6 +70,8 @@ static void _workqueue_thread_entry(void* parameter)
work = rt_list_entry(queue->work_list.next, struct rt_work, list);
rt_list_remove(&(work->list));
queue->work_current = work;
+ work->flags &= ~RT_WORK_STATE_PENDING;
+ work->workqueue = RT_NULL;
rt_hw_interrupt_enable(level);
/* do work */
@@ -81,11 +86,172 @@ static void _workqueue_thread_entry(void* parameter)
}
}
-struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority)
+static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work)
+{
+ rt_base_t level;
+
+ 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 */
+ 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)
+ {
+ rt_hw_interrupt_enable(level);
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_schedule();
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work)
+{
+ rt_base_t level;
+
+ 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
+ {
+ 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);
+ }
+ }
+
+ level = rt_hw_interrupt_disable();
+ /* Detach from workqueue */
+ work->workqueue = RT_NULL;
+ work->flags &= ~(RT_WORK_STATE_PENDING);
+ rt_hw_interrupt_enable(level);
+
+__exit:
+ return ret;
+}
+
+static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue,
+ struct rt_work *work, rt_tick_t ticks)
+{
+ 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;
+ }
+
+ /* Cancel if work has been submitted */
+ if (work->workqueue == queue)
+ {
+ ret = _workqueue_cancel_delayed_work(work);
+ if (ret < 0)
+ {
+ goto __exit;
+ }
+ }
+
+ level = rt_hw_interrupt_disable();
+ /* Attach workqueue so the timeout callback can submit it */
+ work->workqueue = queue;
+ rt_hw_interrupt_enable(level);
+
+ if (!ticks)
+ {
+ /* Submit work if no ticks is 0 */
+ ret = _workqueue_submit_work(work->workqueue, work);
+ }
+ 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)
{
struct rt_workqueue *queue = RT_NULL;
- queue = (struct rt_workqueue*)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue));
+ queue = (struct rt_workqueue *)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue));
if (queue != RT_NULL)
{
/* initialize work list */
@@ -107,7 +273,7 @@ struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_siz
return queue;
}
-rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue)
+rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue)
{
RT_ASSERT(queue != RT_NULL);
@@ -117,37 +283,35 @@ rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue)
return RT_EOK;
}
-rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work)
+rt_err_t rt_workqueue_dowork(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)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
+ return _workqueue_submit_work(queue, work);
+}
- /* NOTE: the work MUST be initialized firstly */
- rt_list_remove(&(work->list));
+rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time)
+{
+ RT_ASSERT(queue != RT_NULL);
+ RT_ASSERT(work != RT_NULL);
- rt_list_insert_after(queue->work_list.prev, &(work->list));
- /* whether the workqueue is doing work */
- if (queue->work_current == RT_NULL)
+ if (time > 0)
{
- rt_hw_interrupt_enable(level);
- /* resume work thread */
- rt_thread_resume(queue->work_thread);
- rt_schedule();
+ work->type |= RT_WORK_TYPE_DELAYED;
}
- else rt_hw_interrupt_enable(level);
- return RT_EOK;
+ if (work->type & RT_WORK_TYPE_DELAYED)
+ {
+ return _workqueue_submit_delayed_work(queue, work, time);
+ }
+ else
+ {
+ return _workqueue_submit_work(queue, work);
+ }
}
-rt_err_t rt_workqueue_critical_work(struct rt_workqueue* queue, struct rt_work* work)
+rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work)
{
rt_base_t level;
RT_ASSERT(queue != RT_NULL);
@@ -176,26 +340,22 @@ rt_err_t rt_workqueue_critical_work(struct rt_workqueue* queue, struct rt_work*
return RT_EOK;
}
-rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work)
+rt_err_t rt_workqueue_cancel_work(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)
+ if (work->type & RT_WORK_TYPE_DELAYED)
{
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
+ return _workqueue_cancel_delayed_work(work);
+ }
+ else
+ {
+ return _workqueue_cancel_work(queue, work);
}
- rt_list_remove(&(work->list));
- rt_hw_interrupt_enable(level);
-
- return RT_EOK;
}
-rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue* queue, struct rt_work* work)
+rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work)
{
rt_base_t level;
@@ -212,12 +372,13 @@ rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue* queue, struct rt_wor
{
rt_list_remove(&(work->list));
}
+ 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)
+rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue)
{
struct rt_list_node *node, *next;
RT_ASSERT(queue != RT_NULL);
@@ -233,5 +394,36 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue* queue)
return RT_EOK;
}
-#endif
+void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work,
+ void *work_data), void *work_data)
+{
+ rt_work_init(&work->work, work_func, work_data);
+}
+
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+static struct rt_workqueue *sys_workq;
+
+rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time)
+{
+ return rt_workqueue_submit_work(sys_workq, work, time);
+}
+
+rt_err_t rt_work_cancel(struct rt_work *work)
+{
+ return rt_workqueue_cancel_work(sys_workq, work);
+}
+
+int rt_work_sys_workqueue_init(void)
+{
+ if (sys_workq != RT_NULL)
+ return 0;
+
+ sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE,
+ RT_SYSTEM_WORKQUEUE_PRIORITY);
+ return RT_EOK;
+}
+
+INIT_DEVICE_EXPORT(rt_work_sys_workqueue_init);
+#endif
+#endif