Forward declared memrar_allocator in memrar_allocator.h and moved it
to memrar_allocator.c file. Implemented memrar_allocator_capacity(),
memrar_allocator_largest_free_area(), memrar_allocoator_lock() and
memrar_allocator_unlock().
Signed-off-by: Henri Häkkinen <[email protected]>
---
drivers/staging/memrar/memrar_allocator.c | 56 ++++++++++++++++++++++++
drivers/staging/memrar/memrar_allocator.h | 66 ++++++++++++++++------------
drivers/staging/memrar/memrar_handler.c | 11 +++--
3 files changed, 100 insertions(+), 33 deletions(-)
diff --git a/drivers/staging/memrar/memrar_allocator.c b/drivers/staging/memrar/memrar_allocator.c
index a4f8c58..955d1eb 100644
--- a/drivers/staging/memrar/memrar_allocator.c
+++ b/drivers/staging/memrar/memrar_allocator.c
@@ -41,6 +41,36 @@
#include <linux/kernel.h>
+/**
+ * struct memrar_allocator - encapsulation of the memory allocator state
+ * @lock: Lock used to synchronize access to the memory
+ * allocator state.
+ * @base: Base (start) address of the allocator memory
+ * space.
+ * @capacity: Size of the allocator memory space in bytes.
+ * @block_size: The size in bytes of individual blocks within
+ * the allocator memory space.
+ * @largest_free_area: Largest free area of memory in the allocator
+ * in bytes.
+ * @allocated_list: List of allocated memory block address
+ * ranges.
+ * @free_list: List of free address ranges.
+ *
+ * This structure contains all memory allocator state, including the
+ * base address, capacity, free list, lock, etc.
+ */
+struct memrar_allocator {
+/* private: internal use only */
+ struct mutex lock;
+ unsigned long base;
+ size_t capacity;
+ size_t block_size;
+ size_t largest_free_area;
+ struct memrar_address_ranges allocated_list;
+ struct memrar_address_ranges free_list;
+};
+
+
struct memrar_allocator *memrar_create_allocator(unsigned long base,
size_t capacity,
size_t block_size)
@@ -423,7 +453,33 @@ exit_memrar_free:
return 0;
}
+size_t memrar_allocator_largest_free_area(struct memrar_allocator *allocator)
+{
+ if (allocator == NULL)
+ return 0;
+ return allocator->largest_free_area;
+}
+
+size_t memrar_allocator_capacity(struct memrar_allocator *allocator)
+{
+ if (allocator == NULL)
+ return 0;
+ return allocator->capacity;
+}
+
+void memrar_allocator_lock(struct memrar_allocator *allocator)
+{
+ if (allocator == NULL)
+ return;
+ mutex_lock(&allocator->lock);
+}
+void memrar_allocator_unlock(struct memrar_allocator *allocator)
+{
+ if (allocator == NULL)
+ return;
+ mutex_unlock(&allocator->lock);
+}
/*
Local Variables:
diff --git a/drivers/staging/memrar/memrar_allocator.h b/drivers/staging/memrar/memrar_allocator.h
index 0b80dea..0417072 100644
--- a/drivers/staging/memrar/memrar_allocator.h
+++ b/drivers/staging/memrar/memrar_allocator.h
@@ -50,34 +50,10 @@ struct memrar_address_ranges {
struct memrar_address_range range;
};
-/**
- * struct memrar_allocator - encapsulation of the memory allocator state
- * @lock: Lock used to synchronize access to the memory
- * allocator state.
- * @base: Base (start) address of the allocator memory
- * space.
- * @capacity: Size of the allocator memory space in bytes.
- * @block_size: The size in bytes of individual blocks within
- * the allocator memory space.
- * @largest_free_area: Largest free area of memory in the allocator
- * in bytes.
- * @allocated_list: List of allocated memory block address
- * ranges.
- * @free_list: List of free address ranges.
- *
- * This structure contains all memory allocator state, including the
- * base address, capacity, free list, lock, etc.
- */
-struct memrar_allocator {
-/* private: internal use only */
- struct mutex lock;
- unsigned long base;
- size_t capacity;
- size_t block_size;
- size_t largest_free_area;
- struct memrar_address_ranges allocated_list;
- struct memrar_address_ranges free_list;
-};
+
+/* Forward declaration */
+struct memrar_allocator;
+
/**
* memrar_create_allocator() - create a memory allocator
@@ -139,6 +115,40 @@ unsigned long memrar_allocator_alloc(struct memrar_allocator *allocator,
long memrar_allocator_free(struct memrar_allocator *allocator,
unsigned long address);
+/**
+ * memrar_allocator_largest_area() - largest free area of memory
+ * @allocator: The allocator instance the free area is returned for.
+ *
+ * Return the largest free area of memory in the allocator in bytes.
+ */
+size_t memrar_allocator_largest_free_area(struct memrar_allocator *allocator);
+
+/**
+ * memrar_allocator_capacity - size of the allocator memory
+ * @allocator: The allocator instance the capicity is returned for.
+ *
+ * Return the size of the allocator memory space in bytes.
+ */
+size_t memrar_allocator_capacity(struct memrar_allocator *allocator);
+
+
+/**
+ * memrar_allocator_lock - lock the allocator's mutex
+ * @allocator: The allocator instance to lock the mutex for.
+ *
+ * Lock the mutex associated with the allocator.
+ */
+void memrar_allocator_lock(struct memrar_allocator *allocator);
+
+
+/**
+ * memrar_allocator_unlock - unlock the allocator's mutex
+ * @allocator: The allocator instance to unlock the mutex for.
+ *
+ * Unlock the mutex associated with the allocator.
+ */
+void memrar_allocator_unlock(struct memrar_allocator *allocator);
+
#endif /* MEMRAR_ALLOCATOR_H */
diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c
index efa7fd6..6a4628c 100644
--- a/drivers/staging/memrar/memrar_handler.c
+++ b/drivers/staging/memrar/memrar_handler.c
@@ -350,7 +350,8 @@ static int memrar_init_rar_resources(int rarnum, char const *devname)
devname, rarnum, (unsigned long) low, (unsigned long) high);
pr_info("%s: BRAR[%d] size = %zu KiB\n",
- devname, rarnum, rar->allocator->capacity / 1024);
+ devname, rarnum,
+ memrar_allocator_capacity(rar->allocator) / 1024);
rar->allocated = 1;
return 0;
@@ -545,11 +546,11 @@ static long memrar_get_stat(struct RAR_stat *r)
* Allocator capacity doesn't change over time. No
* need to synchronize.
*/
- r->capacity = allocator->capacity;
+ r->capacity = memrar_allocator_capacity(allocator);
- mutex_lock(&allocator->lock);
- r->largest_block_size = allocator->largest_free_area;
- mutex_unlock(&allocator->lock);
+ memrar_allocator_lock(allocator);
+ r->largest_block_size = memrar_allocator_largest_free_area(allocator);
+ memrar_allocator_unlock(allocator);
return 0;
}
--
1.7.1
Hi,
> Forward declared memrar_allocator in memrar_allocator.h and moved it
> to memrar_allocator.c file. Implemented memrar_allocator_capacity(),
> memrar_allocator_largest_free_area(), memrar_allocoator_lock() and
> memrar_allocator_unlock().
...
> - mutex_lock(&allocator->lock);
> - r->largest_block_size = allocator->largest_free_area;
> - mutex_unlock(&allocator->lock);
> + memrar_allocator_lock(allocator);
> + r->largest_block_size =
> memrar_allocator_largest_free_area(allocator);
> + memrar_allocator_unlock(allocator);
I don't think it's necessary to expose the allocator lock. Why not just grab the lock in memrar_allocator_largest_free_area() while the underlying struct field is being accessed and then unlock it before that function returns? That would allow the allocator lock to remain an internal implementation detail. We only need to ensure access to the struct field itself is synchronized, e.g.:
size_t memrar_allocator_largest_free_area(struct memrar_allocator *allocator)
{
size_t tmp = 0;
if (allocator != NULL) {
mutex_lock(&allocator->lock);
tmp = allocator->largest_free_area;
mutex_unlock(&allocator->lock);
}
return tmp;
}
Certainly the allocator->largest_free_area value could be updated after the lock is released and by the time it is returned to the user (for statistical purposes), but at least the internal allocator state would remain consistent in the presences of multiple threads.
HTH,
-Ossama
????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m????????????I?
On Mon, Jun 14, 2010 at 03:40:27PM +0300, Henri H?kkinen wrote:
> Forward declared memrar_allocator in memrar_allocator.h and moved it
> to memrar_allocator.c file. Implemented memrar_allocator_capacity(),
> memrar_allocator_largest_free_area(), memrar_allocoator_lock() and
> memrar_allocator_unlock().
Shouldn't this be more than just one single patch?
Please only do one thing per patch.
Care to respin these and take into consideration the other comments for
this patch?
thanks,
greg k-h