atrstm

Load and structure a combustion gas mixture
git clone git://git.meso-star.fr/atrstm.git
Log | Files | Refs | README | LICENSE

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