1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, Linaro Limited 4 * Copyright (c) 2020, Arm Limited 5 */ 6 #include <stdlib.h> 7 #include <string.h> 8 #include <kernel/handle.h> 9 10 /* 11 * Define the initial capacity of the database. It should be a low number 12 * multiple of 2 since some databases a likely to only use a few handles. 13 * Since the algorithm is to doubles up when growing it shouldn't cause a 14 * noticable overhead on large databases. 15 */ 16 #define HANDLE_DB_INITIAL_MAX_PTRS 4 17 18 void handle_db_destroy(struct handle_db *db, void (*ptr_destructor)(void *ptr)) 19 { 20 if (db) { 21 if (ptr_destructor) { 22 size_t n = 0; 23 24 for (n = 0; n < db->max_ptrs; n++) 25 if (db->ptrs[n]) 26 ptr_destructor(db->ptrs[n]); 27 } 28 free(db->ptrs); 29 db->ptrs = NULL; 30 db->max_ptrs = 0; 31 } 32 } 33 34 bool handle_db_is_empty(struct handle_db *db) 35 { 36 size_t n = 0; 37 38 if (db) { 39 for (n = 0; n < db->max_ptrs; n++) { 40 if (db->ptrs[n]) 41 return false; 42 } 43 } 44 return true; 45 } 46 47 int handle_get(struct handle_db *db, void *ptr) 48 { 49 size_t n; 50 void *p; 51 size_t new_max_ptrs; 52 53 if (!db || !ptr) 54 return -1; 55 56 /* Try to find an empty location */ 57 for (n = 0; n < db->max_ptrs; n++) { 58 if (!db->ptrs[n]) { 59 db->ptrs[n] = ptr; 60 return n; 61 } 62 } 63 64 /* No location available, grow the ptrs array */ 65 if (db->max_ptrs) 66 new_max_ptrs = db->max_ptrs * 2; 67 else 68 new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 69 p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); 70 if (!p) 71 return -1; 72 db->ptrs = p; 73 memset(db->ptrs + db->max_ptrs, 0, 74 (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 75 db->max_ptrs = new_max_ptrs; 76 77 /* Since n stopped at db->max_ptrs there is an empty location there */ 78 db->ptrs[n] = ptr; 79 return n; 80 } 81 82 void *handle_put(struct handle_db *db, int handle) 83 { 84 void *p; 85 86 if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) 87 return NULL; 88 89 p = db->ptrs[handle]; 90 db->ptrs[handle] = NULL; 91 return p; 92 } 93 94 void *handle_lookup(struct handle_db *db, int handle) 95 { 96 if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) 97 return NULL; 98 99 return db->ptrs[handle]; 100 } 101