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. |