1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <stdlib.h> 29 #include <string.h> 30 #include <kernel/handle.h> 31 32 /* 33 * Define the initial capacity of the database. It should be a low number 34 * multiple of 2 since some databases a likely to only use a few handles. 35 * Since the algorithm is to doubles up when growing it shouldn't cause a 36 * noticable overhead on large databases. 37 */ 38 #define HANDLE_DB_INITIAL_MAX_PTRS 4 39 40 void handle_db_destroy(struct handle_db *db) 41 { 42 if (db) { 43 free(db->ptrs); 44 db->ptrs = NULL; 45 db->max_ptrs = 0; 46 } 47 } 48 49 int handle_get(struct handle_db *db, void *ptr) 50 { 51 size_t n; 52 void *p; 53 size_t new_max_ptrs; 54 55 if (!db || !ptr) 56 return -1; 57 58 /* Try to find an empty location */ 59 for (n = 0; n < db->max_ptrs; n++) { 60 if (!db->ptrs[n]) { 61 db->ptrs[n] = ptr; 62 return n; 63 } 64 } 65 66 /* No location available, grow the ptrs array */ 67 if (db->max_ptrs) 68 new_max_ptrs = db->max_ptrs * 2; 69 else 70 new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 71 p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); 72 if (!p) 73 return -1; 74 db->ptrs = p; 75 memset(db->ptrs + db->max_ptrs, 0, 76 (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 77 db->max_ptrs = new_max_ptrs; 78 79 /* Since n stopped at db->max_ptrs there is an empty location there */ 80 db->ptrs[n] = ptr; 81 return n; 82 } 83 84 void *handle_put(struct handle_db *db, int handle) 85 { 86 void *p; 87 88 if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) 89 return NULL; 90 91 p = db->ptrs[handle]; 92 db->ptrs[handle] = NULL; 93 return p; 94 } 95 96 void *handle_lookup(struct handle_db *db, int handle) 97 { 98 if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) 99 return NULL; 100 101 return db->ptrs[handle]; 102 } 103