Rev 3538 | Rev 3540 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3538 | Rev 3539 | ||
---|---|---|---|
Line 46... | Line 46... | ||
46 | #include <ipc/ipc.h> |
46 | #include <ipc/ipc.h> |
47 | #include <as.h> |
47 | #include <as.h> |
48 | #include <assert.h> |
48 | #include <assert.h> |
49 | #include <futex.h> |
49 | #include <futex.h> |
50 | #include <libadt/list.h> |
50 | #include <libadt/list.h> |
- | 51 | #include <libadt/hash_table.h> |
|
51 | 52 | ||
52 | /** Lock protecting the device connection list */ |
53 | /** Lock protecting the device connection list */ |
53 | static futex_t dcl_lock = FUTEX_INITIALIZER; |
54 | static futex_t dcl_lock = FUTEX_INITIALIZER; |
54 | /** Device connection list head. */ |
55 | /** Device connection list head. */ |
55 | static LIST_INITIALIZE(dcl_head); |
56 | static LIST_INITIALIZE(dcl_head); |
56 | 57 | ||
- | 58 | #define CACHE_BUCKETS_LOG2 10 |
|
- | 59 | #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) |
|
- | 60 | ||
- | 61 | typedef struct { |
|
- | 62 | futex_t lock; |
|
- | 63 | size_t block_size; /**< Block size. */ |
|
- | 64 | unsigned block_count; /**< Total number of blocks. */ |
|
- | 65 | hash_table_t block_hash; |
|
- | 66 | link_t free_head; |
|
- | 67 | } cache_t; |
|
- | 68 | ||
57 | typedef struct { |
69 | typedef struct { |
58 | link_t link; |
70 | link_t link; |
59 | int dev_handle; |
71 | int dev_handle; |
60 | int dev_phone; |
72 | int dev_phone; |
61 | void *com_area; |
73 | void *com_area; |
62 | size_t com_size; |
74 | size_t com_size; |
63 | void *bb_buf; |
75 | void *bb_buf; |
64 | off_t bb_off; |
76 | off_t bb_off; |
65 | size_t bb_size; |
77 | size_t bb_size; |
- | 78 | cache_t *cache; |
|
66 | } devcon_t; |
79 | } devcon_t; |
67 | 80 | ||
68 | static devcon_t *devcon_search(dev_handle_t dev_handle) |
81 | static devcon_t *devcon_search(dev_handle_t dev_handle) |
69 | { |
82 | { |
70 | link_t *cur; |
83 | link_t *cur; |
Line 97... | Line 110... | ||
97 | devcon->com_area = com_area; |
110 | devcon->com_area = com_area; |
98 | devcon->com_size = com_size; |
111 | devcon->com_size = com_size; |
99 | devcon->bb_buf = NULL; |
112 | devcon->bb_buf = NULL; |
100 | devcon->bb_off = 0; |
113 | devcon->bb_off = 0; |
101 | devcon->bb_size = 0; |
114 | devcon->bb_size = 0; |
- | 115 | devcon->cache = NULL; |
|
102 | 116 | ||
103 | futex_down(&dcl_lock); |
117 | futex_down(&dcl_lock); |
104 | for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
118 | for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { |
105 | devcon_t *d = list_get_instance(cur, devcon_t, link); |
119 | devcon_t *d = list_get_instance(cur, devcon_t, link); |
106 | if (d->dev_handle == dev_handle) { |
120 | if (d->dev_handle == dev_handle) { |
Line 165... | Line 179... | ||
165 | 179 | ||
166 | devcon_remove(devcon); |
180 | devcon_remove(devcon); |
167 | 181 | ||
168 | if (devcon->bb_buf) |
182 | if (devcon->bb_buf) |
169 | free(devcon->bb_buf); |
183 | free(devcon->bb_buf); |
- | 184 | ||
- | 185 | if (devcon->cache) { |
|
- | 186 | hash_table_destroy(&devcon->cache->block_hash); |
|
- | 187 | free(devcon->cache); |
|
- | 188 | } |
|
- | 189 | ||
170 | munmap(devcon->com_area, devcon->com_size); |
190 | munmap(devcon->com_area, devcon->com_size); |
171 | ipc_hangup(devcon->dev_phone); |
191 | ipc_hangup(devcon->dev_phone); |
172 | 192 | ||
173 | free(devcon); |
193 | free(devcon); |
174 | } |
194 | } |
Line 207... | Line 227... | ||
207 | devcon_t *devcon = devcon_search(dev_handle); |
227 | devcon_t *devcon = devcon_search(dev_handle); |
208 | assert(devcon); |
228 | assert(devcon); |
209 | return devcon->bb_buf; |
229 | return devcon->bb_buf; |
210 | } |
230 | } |
211 | 231 | ||
- | 232 | static hash_index_t cache_hash(unsigned long *key) |
|
- | 233 | { |
|
- | 234 | return *key & (CACHE_BUCKETS - 1); |
|
- | 235 | } |
|
- | 236 | ||
- | 237 | static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) |
|
- | 238 | { |
|
- | 239 | block_t *b = hash_table_get_instance(item, block_t, hash_link); |
|
- | 240 | return b->boff == *key; |
|
- | 241 | } |
|
- | 242 | ||
- | 243 | static void cache_remove_callback(link_t *item) |
|
- | 244 | { |
|
- | 245 | } |
|
- | 246 | ||
- | 247 | static hash_table_operations_t cache_ops = { |
|
- | 248 | .hash = cache_hash, |
|
- | 249 | .compare = cache_compare, |
|
- | 250 | .remove_callback = cache_remove_callback |
|
- | 251 | }; |
|
- | 252 | ||
- | 253 | int block_cache_init(dev_handle_t dev_handle, size_t size, unsigned blocks) |
|
- | 254 | { |
|
- | 255 | devcon_t *devcon = devcon_search(dev_handle); |
|
- | 256 | cache_t *cache; |
|
- | 257 | if (!devcon) |
|
- | 258 | return ENOENT; |
|
- | 259 | if (devcon->cache) |
|
- | 260 | return EEXIST; |
|
- | 261 | cache = malloc(sizeof(cache_t)); |
|
- | 262 | if (!cache) |
|
- | 263 | return ENOMEM; |
|
- | 264 | ||
- | 265 | futex_initialize(&cache->lock, 0); |
|
- | 266 | list_initialize(&cache->free_head); |
|
- | 267 | cache->block_size = size; |
|
- | 268 | cache->block_count = blocks; |
|
- | 269 | ||
- | 270 | if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, |
|
- | 271 | &cache_ops)) { |
|
- | 272 | free(cache); |
|
- | 273 | return ENOMEM; |
|
- | 274 | } |
|
- | 275 | ||
- | 276 | devcon->cache = cache; |
|
- | 277 | return EOK; |
|
- | 278 | } |
|
- | 279 | ||
212 | /** Read data from a block device. |
280 | /** Read data from a block device. |
213 | * |
281 | * |
214 | * @param dev_handle Device handle of the block device. |
282 | * @param dev_handle Device handle of the block device. |
215 | * @param bufpos Pointer to the first unread valid offset within the |
283 | * @param bufpos Pointer to the first unread valid offset within the |
216 | * communication buffer. |
284 | * communication buffer. |