atrstm_partition.c (5289B)
1 /* Copyright (C) 2022, 2023 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2020, 2021 Centre National de la Recherche Scientifique 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "atrstm_log.h" 18 #include "atrstm_partition.h" 19 20 #include <rsys/condition.h> 21 #include <rsys/mem_allocator.h> 22 #include <rsys/mutex.h> 23 24 /****************************************************************************** 25 * Local functions 26 ******************************************************************************/ 27 res_T 28 pool_init 29 (struct mem_allocator* mem_allocator, 30 const size_t nparts, 31 struct pool* pool) 32 { 33 size_t ipart; 34 res_T res = RES_OK; 35 ASSERT(pool && nparts); 36 37 memset(pool, 0, sizeof(*pool)); 38 39 list_init(&pool->parts_free); 40 list_init(&pool->parts_full); 41 pool->allocator = mem_allocator ? mem_allocator : &mem_default_allocator; 42 43 pool->mutex = mutex_create(); 44 if(!pool->mutex) { res = RES_UNKNOWN_ERR; goto error; } 45 pool->cond_new = cond_create(); 46 if(!pool->cond_new) { res = RES_UNKNOWN_ERR; goto error; } 47 pool->cond_fetch = cond_create(); 48 if(!pool->cond_fetch) { res = RES_UNKNOWN_ERR; goto error; } 49 50 FOR_EACH(ipart, 0, nparts) { 51 struct part* part = MEM_ALLOC_ALIGNED(pool->allocator, sizeof(*part), 64); 52 if(!part) { 53 res = RES_MEM_ERR; 54 goto error; 55 } 56 part_init(part); 57 list_add(&pool->parts_free, &part->node); 58 } 59 60 exit: 61 return res; 62 error: 63 pool_release(pool); 64 goto exit; 65 } 66 67 void 68 pool_release(struct pool* pool) 69 { 70 struct list_node* node; 71 struct list_node* tmp_node; 72 ASSERT(pool); 73 74 if(pool->mutex) mutex_destroy(pool->mutex); 75 if(pool->cond_new) cond_destroy(pool->cond_new); 76 if(pool->cond_fetch) cond_destroy(pool->cond_fetch); 77 78 if(pool->parts_free.next != NULL) { /* Is list initialised */ 79 LIST_FOR_EACH_SAFE(node, tmp_node, &pool->parts_free) { 80 struct part* part = CONTAINER_OF(node, struct part, node); 81 list_del(node); 82 part_release(part); 83 MEM_RM(pool->allocator, part); 84 } 85 ASSERT(is_list_empty(&pool->parts_free)); 86 } 87 88 if(pool->parts_full.next != NULL) { /* Is list initialised */ 89 LIST_FOR_EACH_SAFE(node, tmp_node, &pool->parts_full) { 90 struct part* part = CONTAINER_OF(node, struct part, node); 91 list_del(node); 92 part_release(part); 93 MEM_RM(pool->allocator, part); 94 } 95 ASSERT(is_list_empty(&pool->parts_full)); 96 } 97 98 memset(pool, 0, sizeof(*pool)); 99 } 100 101 struct part* 102 pool_next_partition(struct pool* pool) 103 { 104 struct list_node* node = NULL; 105 struct part* part = NULL; 106 ASSERT(pool); 107 108 mutex_lock(pool->mutex); 109 while(is_list_empty(&pool->parts_free) && !pool->error) { 110 cond_wait(pool->cond_new, pool->mutex); 111 } 112 if(pool->error) { 113 part = NULL; 114 mutex_unlock(pool->mutex); 115 } else { 116 size_t ipart; 117 node = list_head(&pool->parts_free); 118 list_del(node); 119 ipart = pool->next_part_id++; 120 mutex_unlock(pool->mutex); 121 122 part = CONTAINER_OF(node, struct part, node); 123 part->id = ipart; 124 } 125 return part; 126 } 127 128 void 129 pool_free_partition(struct pool* pool, struct part* part) 130 { 131 ASSERT(pool && part); 132 133 mutex_lock(pool->mutex); 134 list_move_tail(&part->node, &pool->parts_free); 135 mutex_unlock(pool->mutex); 136 137 cond_signal(pool->cond_new); 138 } 139 140 void 141 pool_commit_partition(struct pool* pool, struct part* part) 142 { 143 struct list_node* node = NULL; 144 ASSERT(pool && part); 145 146 mutex_lock(pool->mutex); 147 LIST_FOR_EACH_REVERSE(node, &pool->parts_full) { 148 struct part* part2 = CONTAINER_OF(node, struct part, node); 149 if(part2->id <= part->id) break; 150 } 151 list_add(node, &part->node); 152 mutex_unlock(pool->mutex); 153 154 cond_signal(pool->cond_fetch); 155 } 156 157 struct part* 158 pool_fetch_partition(struct pool* pool, const size_t part_id) 159 { 160 struct part* found_part = NULL; 161 struct list_node* node = NULL; 162 ASSERT(pool); 163 164 mutex_lock(pool->mutex); 165 while(!pool->error) { 166 /* Search for a partition that match the submitted id */ 167 LIST_FOR_EACH(node, &pool->parts_full) { 168 struct part* part = CONTAINER_OF(node, struct part, node); 169 170 if(part->id == part_id) { 171 found_part = part; 172 break; 173 } 174 175 /* Partitions are sorted in ascending order. Stop the linear search if the 176 * current id is greater than the submitted one */ 177 if(part->id > part_id) break; 178 } 179 if(!found_part) { 180 cond_wait(pool->cond_fetch, pool->mutex); 181 } else { 182 /*list_del(&found_part->node);*/ 183 break; 184 } 185 } 186 mutex_unlock(pool->mutex); 187 188 return found_part; 189 } 190 191 void 192 pool_invalidate(struct pool* pool) 193 { 194 ASSERT(pool); 195 mutex_lock(pool->mutex); 196 pool->error = 1; 197 mutex_unlock(pool->mutex); 198 199 cond_broadcast(pool->cond_new); 200 cond_broadcast(pool->cond_fetch); 201 } 202