From 7bcce9e87fa987d4bb88d48d3f7d0aca58963e74 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 9 Jul 2013 11:54:50 +0800 Subject: [PATCH] device: add ref_count support This is a simple work around to the current device stack design. A ref_count could let different modules to open/close the same device independently without interfere others in some degree. But there is still some data shared between the modules, like flag, open_flag and user_data. Moreover, it won't yield an error if A open a device, and B read from it before open it in B. Maybe alloc a new handle in rt_device_open will be the ultimate solution. But that is much bigger change and we may leave it to future development. --- include/rtdef.h | 1 + src/device.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/rtdef.h b/include/rtdef.h index 9aaf90b714..8fd4518642 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -779,6 +779,7 @@ struct rt_device rt_uint16_t flag; /**< device flag */ rt_uint16_t open_flag; /**< device open flag */ + rt_uint8_t ref_count; /**< reference count */ rt_uint8_t device_id; /**< 0 - 255 */ /* device call back */ diff --git a/src/device.c b/src/device.c index 1335c7fd2c..75b88bf6eb 100644 --- a/src/device.c +++ b/src/device.c @@ -1,7 +1,7 @@ /* * File : device.c * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ * 2012-10-20 Bernard add device check in register function, * provided by Rob * 2012-12-25 Bernard return RT_EOK if the device interface not exist. + * 2013-07-09 Grissiom add ref_count support */ #include @@ -51,6 +52,7 @@ rt_err_t rt_device_register(rt_device_t dev, rt_object_init(&(dev->parent), RT_Object_Class_Device, name); dev->flag = flags; + dev->ref_count = 0; return RT_EOK; } @@ -237,6 +239,11 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag) return -RT_EBUSY; } + dev->ref_count++; + /* don't let bad things happen silently. If you are bitten by this assert, + * please set the ref_count to a bigger type. */ + RT_ASSERT(dev->ref_count != 0); + /* call device open interface */ if (dev->open != RT_NULL) { @@ -264,6 +271,14 @@ rt_err_t rt_device_close(rt_device_t dev) RT_ASSERT(dev != RT_NULL); + if (dev->ref_count == 0) + return -RT_ERROR; + + dev->ref_count--; + + if (dev->ref_count != 0) + return RT_EOK; + /* call device close interface */ if (dev->close != RT_NULL) { @@ -297,6 +312,12 @@ rt_size_t rt_device_read(rt_device_t dev, { RT_ASSERT(dev != RT_NULL); + if (dev->ref_count == 0) + { + rt_set_errno(-RT_ERROR); + return 0; + } + /* call device read interface */ if (dev->read != RT_NULL) { @@ -329,6 +350,12 @@ rt_size_t rt_device_write(rt_device_t dev, { RT_ASSERT(dev != RT_NULL); + if (dev->ref_count == 0) + { + rt_set_errno(-RT_ERROR); + return 0; + } + /* call device write interface */ if (dev->write != RT_NULL) {