From: Mateusz Majewski Date: Tue, 23 Aug 2022 12:05:16 +0000 (+0200) Subject: hashtable X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4cfa023da39eb9a6b4554373d76e7ef98d9ad739;p=platform%2Fkernel%2Flinux-tizen-modules-source.git hashtable Change-Id: I859bd4954ec9243cab3417c0b50f1309d05941c3 --- diff --git a/kernel/vlogger/vlogger.c b/kernel/vlogger/vlogger.c index 8dd4901..536bcae 100644 --- a/kernel/vlogger/vlogger.c +++ b/kernel/vlogger/vlogger.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #define MB (1 << 20) @@ -46,8 +47,6 @@ #define V_BLOCK_SIZE (2 * KB) #define BLOCK_COUNT (BUFFER_SIZE / V_BLOCK_SIZE) #define DATA_MAX (V_BLOCK_SIZE - sizeof(struct head_t)) -// TODO: We do not want to have a MAX_THREAD limitation. Remove this. -#define MAX_THREAD (0x8000) #define MS_PER_SEC (1000) #define NS_PER_SEC (1000000000UL) @@ -93,6 +92,16 @@ struct queue_t { uint16_t *values; }; +struct thread_table_field { + pid_t tid; + uint16_t blk; + struct hlist_node next; +}; + +struct thread_table { + DECLARE_HASHTABLE(data, 16); +}; + // taken from dlog.h typedef enum { DLOG_UNKNOWN = 0, /**< Keep this always at the start */ @@ -125,12 +134,8 @@ static struct miscdevice vlogger_device; static int g_init; static char *g_shm_ptr[DEVICE_COUNT]; -// TODO: Having an array indexed by TIDs is unnacceptable. -static struct thread_t *g_threads; +static struct thread_table *g_thread_table; -// TODO: g_block_mutex is basically smoke and mirrors, -// since the protected array is basically world-writable -// and can change at any time. static struct mutex g_block_mutex; static struct mutex g_task_mutex; @@ -158,6 +163,44 @@ static inline u64 ktime_get_ns(void) } #endif +static uint16_t get_thread_table(pid_t tid) +{ + struct thread_table_field *ptr = NULL; + + // TODO: Is this needed? + if (g_thread_table == NULL) + return 0; + + hash_for_each_possible(g_thread_table->data, ptr, next, tid) { + if (ptr->tid == tid) { + return ptr->blk; + } + } + + return 0; +} + +static void set_thread_table(pid_t tid, uint16_t blk) +{ + struct thread_table_field *ptr = NULL; + + // TODO: Is this needed? + if (g_thread_table == NULL) + return; + + hash_for_each_possible(g_thread_table->data, ptr, next, tid) { + if (ptr->tid == tid) { + ptr->blk = blk; + return; + } + } + + ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); + ptr->tid = tid; + ptr->blk = blk; + hash_add(g_thread_table->data, &ptr->next, tid); +} + static inline char *get_shared_memory(int dev_index) { if (dev_index < 0 || dev_index >= DEVICE_COUNT) { @@ -241,14 +284,15 @@ static int vlog_task(void *user_data) uint16_t blk; do { + // TODO: Consider hash_for_each_safe for (i = 1; i <= g_max_thread_id; i++) { - blk = g_threads[i].block; + blk = get_thread_table(i); // TODO: g_start_time should be under some kind of mutex. if (blk && get_block(blk)->head.ts < g_start_time) { mutex_lock(&g_block_mutex); get_block(blk)->head.tid = 0; queue_push(&g_free_q, blk); - g_threads[i].block = 0; + set_thread_table(i, 0); // TODO: The userspace might very well be using this block right now. mutex_unlock(&g_block_mutex); g_free_count++; @@ -296,20 +340,15 @@ static long alloc_block_for_thread(void) uint16_t blk; struct block_t *block; - if (tid >= MAX_THREAD) { - pr_err("Invalid tid: %d", tid); - return -EINVAL; - } - if (g_max_thread_id < tid) g_max_thread_id = tid; mutex_lock(&g_block_mutex); - blk = g_threads[tid].block; + blk = get_thread_table(tid); if (blk) queue_push(&g_free_q, blk); blk = queue_pop(&g_free_q); - g_threads[tid].block = blk; + set_thread_table(tid, blk); if (!blk) { if ((g_err_count++ % 10000) < 3) @@ -338,10 +377,7 @@ static inline struct block_t *get_valid_block(int tid, size_t len) uint16_t blk = 0; long r; - if (g_threads == NULL) - return NULL; - - blk = g_threads[tid].block; + blk = get_thread_table(tid); if (blk != 0) { struct block_t *block = get_block(blk); @@ -620,18 +656,19 @@ static const struct file_operations vlogger_fops = { static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { - int thread_count = 0; - int i; - - for (i = 0; i < MAX_THREAD; i++) { - if (g_threads[i].block > 0) - thread_count ++; - } - - return snprintf(buf, PAGE_SIZE, - "free(%d%%):%d/%d task_on:%d gc_free:%u error:%u tid_max:%d\n", - BLOCK_RATIO(g_free_q.count), g_free_q.count, (g_free_q.count + thread_count), - g_task_on, g_free_count, g_err_count, g_max_thread_id); + // int thread_count = 0; + // int i; + + // for (i = 0; i < MAX_THREAD; i++) { + // if (g_threads[i].block > 0) + // thread_count ++; + // } + + // return snprintf(buf, PAGE_SIZE, + // "free(%d%%):%d/%d task_on:%d gc_free:%u error:%u tid_max:%d\n", + // BLOCK_RATIO(g_free_q.count), g_free_q.count, (g_free_q.count + thread_count), + // g_task_on, g_free_count, g_err_count, g_max_thread_id); + return -ENOTSUPP; // TODO } static DEVICE_ATTR_RO(status); @@ -702,7 +739,8 @@ static ssize_t thread_store(struct device *dev, static ssize_t thread_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "[%d] block:%u\n", g_thread, g_threads[g_thread].block); + // return snprintf(buf, PAGE_SIZE, "[%d] block:%u\n", g_thread, g_threads[g_thread].block); + return -ENOTSUPP; // TODO } static DEVICE_ATTR_RW(thread); @@ -749,15 +787,16 @@ int __init vlogger_init(void) return r; } - g_threads = kzalloc(sizeof(struct thread_t) * MAX_THREAD, GFP_KERNEL); - if (g_threads == NULL) + g_thread_table = kzalloc(sizeof(struct thread_table), GFP_KERNEL); + if (g_thread_table == NULL) return -ENOMEM; + hash_init(g_thread_table->data); for (g_shm_ptr_i = 0; g_shm_ptr_i < DEVICE_COUNT; g_shm_ptr_i++) { g_shm_ptr[g_shm_ptr_i] = kzalloc(MAP_SIZE, GFP_KERNEL); if (g_shm_ptr[g_shm_ptr_i] == NULL) { r = -ENOMEM; - goto out_free_g_threads_g_shm_ptr; + goto out_free_g_thread_table_g_shm_ptr; } } @@ -780,10 +819,10 @@ int __init vlogger_init(void) return 0; -out_free_g_threads_g_shm_ptr: +out_free_g_thread_table_g_shm_ptr: for (i = 0; i < g_shm_ptr_i; ++i) kfree(g_shm_ptr[i]); - kfree(g_threads); + kfree(g_thread_table); return r; } @@ -794,7 +833,7 @@ static void __exit vlogger_exit(void) // TODO: What about the task that is running in the background? queue_deinit(&g_free_q); - kfree(g_threads); + kfree(g_thread_table); // TODO: Free innards for (i = 0; i < DEVICE_COUNT; i++) kfree(g_shm_ptr[i]);