<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13177">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">generalize slotmap to make use of it outside of bankd<br><br>Change-Id: I0ca7feaa38dfd0468814ef5a1eff997ce854cedf<br>---<br>M src/Makefile.am<br>M src/bankd.h<br>M src/bankd_main.c<br>D src/bankd_slotmap.c<br>A src/slotmap.c<br>A src/slotmap.h<br>6 files changed, 181 insertions(+), 160 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index 5f0d846..a44906b 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -12,7 +12,7 @@</span><br><span>                          rspro/libosmo-asn1-rspro.la</span><br><span> libosmo_rspro_la_SOURCES = rspro_util.c</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-noinst_HEADERS = debug.h bankd.h client.h internal.h rspro_util.h \</span><br><span style="color: hsl(120, 100%, 40%);">+noinst_HEADERS = debug.h bankd.h client.h internal.h rspro_util.h slotmap.h \</span><br><span>                simtrace2/apdu_dispatch.h \</span><br><span>                  simtrace2/libusb_util.h \</span><br><span>            simtrace2/simtrace2-discovery.h \</span><br><span>@@ -25,7 +25,7 @@</span><br><span> pcsc_test_LDADD = $(OSMOCORE_LIBS) \</span><br><span>                 $(PCSC_LIBS) libosmo-rspro.la</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-remsim_bankd_SOURCES = bankd_slotmap.c bankd_main.c bankd_pcsc.c debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+remsim_bankd_SOURCES = slotmap.c bankd_main.c bankd_pcsc.c debug.c</span><br><span> remsim_bankd_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) \</span><br><span>                $(PCSC_LIBS) libosmo-rspro.la -lcsv</span><br><span> </span><br><span>diff --git a/src/bankd.h b/src/bankd.h</span><br><span>index 86b75cc..cd97772 100644</span><br><span>--- a/src/bankd.h</span><br><span>+++ b/src/bankd.h</span><br><span>@@ -13,60 +13,11 @@</span><br><span> #include <osmocom/core/linuxlist.h></span><br><span> </span><br><span> #include "rspro_util.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "slotmap.h"</span><br><span> #include "debug.h"</span><br><span> </span><br><span> struct bankd;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct bank_slot {</span><br><span style="color: hsl(0, 100%, 40%);">-    uint16_t bank_id;</span><br><span style="color: hsl(0, 100%, 40%);">-       uint16_t slot_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static inline bool bank_slot_equals(const struct bank_slot *a, const struct bank_slot *b)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   if (a->bank_id == b->bank_id && a->slot_nr == b->slot_nr)</span><br><span style="color: hsl(0, 100%, 40%);">-           return true;</span><br><span style="color: hsl(0, 100%, 40%);">-    else</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct client_slot {</span><br><span style="color: hsl(0, 100%, 40%);">-      uint16_t client_id;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint16_t slot_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static inline bool client_slot_equals(const struct client_slot *a, const struct client_slot *b)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     if (a->client_id == b->client_id && a->slot_nr == b->slot_nr)</span><br><span style="color: hsl(0, 100%, 40%);">-               return true;</span><br><span style="color: hsl(0, 100%, 40%);">-    else</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* slot mappings are created / removed by the server */</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_slot_mapping {</span><br><span style="color: hsl(0, 100%, 40%);">-        /* global lits of bankd slot mappings */</span><br><span style="color: hsl(0, 100%, 40%);">-        struct llist_head list;</span><br><span style="color: hsl(0, 100%, 40%);">- /* slot on bank side */</span><br><span style="color: hsl(0, 100%, 40%);">- struct bank_slot bank;</span><br><span style="color: hsl(0, 100%, 40%);">-  /* slot on client side */</span><br><span style="color: hsl(0, 100%, 40%);">-       struct client_slot client;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe lookup of map by client:slot */</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_slot_mapping *bankd_slotmap_by_client(struct bankd *bankd,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                  const struct client_slot *client);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe lookup of map by bank:slot */</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_slot_mapping *bankd_slotmap_by_bank(struct bankd *bankd, const struct bank_slot *bank);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe creating of a new bank<->client map */</span><br><span style="color: hsl(0, 100%, 40%);">-int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank,</span><br><span style="color: hsl(0, 100%, 40%);">-                      const struct client_slot *client);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe removal of a bank<->client map */</span><br><span style="color: hsl(0, 100%, 40%);">-void bankd_slotmap_del(struct bankd *bankd, struct bankd_slot_mapping *map);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> enum bankd_worker_state {</span><br><span>      /* just started*/</span><br><span>    BW_ST_INIT,</span><br><span>@@ -138,9 +89,8 @@</span><br><span>     /* TCP socket at which we are listening */</span><br><span>   int accept_fd;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* list of slit mappings. only ever modified in main thread! */</span><br><span style="color: hsl(0, 100%, 40%);">- struct llist_head slot_mappings;</span><br><span style="color: hsl(0, 100%, 40%);">-        pthread_rwlock_t slot_mappings_rwlock;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* list of slot mappings. only ever modified in main thread! */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct slotmaps *slotmaps;</span><br><span> </span><br><span>       /* list of bankd_workers. accessed/modified by multiple threads; protected by mutex */</span><br><span>       struct llist_head workers;</span><br><span>diff --git a/src/bankd_main.c b/src/bankd_main.c</span><br><span>index fde03cd..ed225a9 100644</span><br><span>--- a/src/bankd_main.c</span><br><span>+++ b/src/bankd_main.c</span><br><span>@@ -47,8 +47,7 @@</span><br><span>  asn_debug = 0;</span><br><span> </span><br><span>   /* intialize members of 'bankd' */</span><br><span style="color: hsl(0, 100%, 40%);">-      INIT_LLIST_HEAD(&bankd->slot_mappings);</span><br><span style="color: hsl(0, 100%, 40%);">-  pthread_rwlock_init(&bankd->slot_mappings_rwlock, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       bankd->slotmaps = slotmap_init(bankd);</span><br><span>    INIT_LLIST_HEAD(&bankd->workers);</span><br><span>     pthread_mutex_init(&bankd->workers_mutex, NULL);</span><br><span> </span><br><span>@@ -71,7 +70,7 @@</span><br><span>              int i;</span><br><span>               for (i = 0; i < 5; i++) {</span><br><span>                         bs.slot_nr = cs.slot_nr = i;</span><br><span style="color: hsl(0, 100%, 40%);">-                    bankd_slotmap_add(bankd, &bs, &cs);</span><br><span style="color: hsl(120, 100%, 40%);">+                   slotmap_add(bankd->slotmaps, &bs, &cs);</span><br><span>           }</span><br><span>    }</span><br><span> }</span><br><span>@@ -304,9 +303,9 @@</span><br><span> /* attempt to obtain slot-map */</span><br><span> static int worker_try_slotmap(struct bankd_worker *worker)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     struct bankd_slot_mapping *slmap;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct slot_mapping *slmap;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- slmap = bankd_slotmap_by_client(worker->bankd, &worker->client.clslot);</span><br><span style="color: hsl(120, 100%, 40%);">+     slmap = slotmap_by_client(worker->bankd->slotmaps, &worker->client.clslot);</span><br><span>     if (!slmap) {</span><br><span>                LOGW(worker, "No slotmap (yet) for client C(%u:%u)\n",</span><br><span>                     worker->client.clslot.client_id, worker->client.clslot.slot_nr);</span><br><span>diff --git a/src/bankd_slotmap.c b/src/bankd_slotmap.c</span><br><span>deleted file mode 100644</span><br><span>index 116fd69..0000000</span><br><span>--- a/src/bankd_slotmap.c</span><br><span>+++ /dev/null</span><br><span>@@ -1,100 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdint.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdlib.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdio.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <errno.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <pthread.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <talloc.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "bankd.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe lookup of map by client:slot */</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_slot_mapping *bankd_slotmap_by_client(struct bankd *bankd, const struct client_slot *client)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct bankd_slot_mapping *map;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry(map, &bankd->slot_mappings, list) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (client_slot_equals(&map->client, client)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-                     return map;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe lookup of map by bank:slot */</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_slot_mapping *bankd_slotmap_by_bank(struct bankd *bankd, const struct bank_slot *bank)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct bankd_slot_mapping *map;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry(map, &bankd->slot_mappings, list) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (bank_slot_equals(&map->bank, bank)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-                     return map;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe creating of a new bank<->client map */</span><br><span style="color: hsl(0, 100%, 40%);">-int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank, const struct client_slot *client)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     struct bankd_slot_mapping *map;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* We assume a single thread (main thread) will ever update the mappings,</span><br><span style="color: hsl(0, 100%, 40%);">-        * and hence we don't have any races by first grabbing + releasing the read</span><br><span style="color: hsl(0, 100%, 40%);">-  * lock twice before grabbing the writelock below */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    map = bankd_slotmap_by_bank(bankd, bank);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (map) {</span><br><span style="color: hsl(0, 100%, 40%);">-              fprintf(stderr, "BANKD %u:%u already in use, cannot add new map\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                   bank->bank_id, bank->slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-            return -EBUSY;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       map = bankd_slotmap_by_client(bankd, client);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (map) {</span><br><span style="color: hsl(0, 100%, 40%);">-              fprintf(stderr, "CLIENT %u:%u already in use, cannot add new map\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  client->client_id, client->slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-              return -EBUSY;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* allocate new mapping and add to list of mappings */</span><br><span style="color: hsl(0, 100%, 40%);">-  map = talloc_zero(bankd, struct bankd_slot_mapping);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!map)</span><br><span style="color: hsl(0, 100%, 40%);">-               return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- map->bank = *bank;</span><br><span style="color: hsl(0, 100%, 40%);">-   map->client = *client;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_add_tail(&map->list, &bankd->slot_mappings);</span><br><span style="color: hsl(0, 100%, 40%);">-        pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     printf("Added Slot Map C(%u:%u) <-> B(%u:%u)\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* thread-safe removal of a bank<->client map */</span><br><span style="color: hsl(0, 100%, 40%);">-void bankd_slotmap_del(struct bankd *bankd, struct bankd_slot_mapping *map)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    printf("Deleting Slot Map C(%u:%u) <-> B(%u:%u)\n",</span><br><span style="color: hsl(0, 100%, 40%);">-             map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_del(&map->list);</span><br><span style="color: hsl(0, 100%, 40%);">-   pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     talloc_free(map);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span>diff --git a/src/slotmap.c b/src/slotmap.c</span><br><span>new file mode 100644</span><br><span>index 0000000..303f5fd</span><br><span>--- /dev/null</span><br><span>+++ b/src/slotmap.c</span><br><span>@@ -0,0 +1,110 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <pthread.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "slotmap.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe lookup of map by client:slot */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slot_mapping *slotmap_by_client(struct slotmaps *maps, const struct client_slot *client)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct slot_mapping *map;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   pthread_rwlock_rdlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_for_each_entry(map, &maps->mappings, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (client_slot_equals(&map->client, client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+                  return map;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe lookup of map by bank:slot */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slot_mapping *slotmap_by_bank(struct slotmaps *maps, const struct bank_slot *bank)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct slot_mapping *map;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   pthread_rwlock_rdlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_for_each_entry(map, &maps->mappings, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (bank_slot_equals(&map->bank, bank)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+                  return map;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe creating of a new bank<->client map */</span><br><span style="color: hsl(120, 100%, 40%);">+int slotmap_add(struct slotmaps *maps, const struct bank_slot *bank, const struct client_slot *client)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct slot_mapping *map;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* We assume a single thread (main thread) will ever update the mappings,</span><br><span style="color: hsl(120, 100%, 40%);">+      * and hence we don't have any races by first grabbing + releasing the read</span><br><span style="color: hsl(120, 100%, 40%);">+        * lock twice before grabbing the writelock below */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        map = slotmap_by_bank(maps, bank);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (map) {</span><br><span style="color: hsl(120, 100%, 40%);">+            fprintf(stderr, "BANKD %u:%u already in use, cannot add new map\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 bank->bank_id, bank->slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EBUSY;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   map = slotmap_by_client(maps, client);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (map) {</span><br><span style="color: hsl(120, 100%, 40%);">+            fprintf(stderr, "CLIENT %u:%u already in use, cannot add new map\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        client->client_id, client->slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EBUSY;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* allocate new mapping and add to list of mappings */</span><br><span style="color: hsl(120, 100%, 40%);">+        map = talloc_zero(maps, struct slot_mapping);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!map)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     map->bank = *bank;</span><br><span style="color: hsl(120, 100%, 40%);">+ map->client = *client;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   pthread_rwlock_wrlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_add_tail(&map->list, &maps->mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+    pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("Added Slot Map C(%u:%u) <-> B(%u:%u)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe removal of a bank<->client map */</span><br><span style="color: hsl(120, 100%, 40%);">+void slotmap_del(struct slotmaps *maps, struct slot_mapping *map)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Deleting Slot Map C(%u:%u) <-> B(%u:%u)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+           map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      pthread_rwlock_wrlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+  llist_del(&map->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_rwlock_unlock(&maps->rwlock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(map);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct slotmaps *slotmap_init(void *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct slotmaps *sm = talloc_zero(ctx, struct slotmaps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    INIT_LLIST_HEAD(&sm->mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+        pthread_rwlock_init(&sm->rwlock, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return sm;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/slotmap.h b/src/slotmap.h</span><br><span>new file mode 100644</span><br><span>index 0000000..92eb6f4</span><br><span>--- /dev/null</span><br><span>+++ b/src/slotmap.h</span><br><span>@@ -0,0 +1,62 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <pthread.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/linuxlist.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bank_slot {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t bank_id;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t slot_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool bank_slot_equals(const struct bank_slot *a, const struct bank_slot *b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->bank_id == b->bank_id && a->slot_nr == b->slot_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+         return true;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct client_slot {</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t client_id;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint16_t slot_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool client_slot_equals(const struct client_slot *a, const struct client_slot *b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (a->client_id == b->client_id && a->slot_nr == b->slot_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+             return true;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* slot mappings are created / removed by the server */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slot_mapping {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* global lits of bankd slot mappings */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* slot on bank side */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct bank_slot bank;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* slot on client side */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct client_slot client;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* collection of slot mappings */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slotmaps {</span><br><span style="color: hsl(120, 100%, 40%);">+        struct llist_head mappings;</span><br><span style="color: hsl(120, 100%, 40%);">+   pthread_rwlock_t rwlock;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe lookup of map by client:slot */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slot_mapping *slotmap_by_client(struct slotmaps *maps, const struct client_slot *client);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe lookup of map by bank:slot */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slot_mapping *slotmap_by_bank(struct slotmaps *maps, const struct bank_slot *bank);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe creating of a new bank<->client map */</span><br><span style="color: hsl(120, 100%, 40%);">+int slotmap_add(struct slotmaps *maps, const struct bank_slot *bank, const struct client_slot *client);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* thread-safe removal of a bank<->client map */</span><br><span style="color: hsl(120, 100%, 40%);">+void slotmap_del(struct slotmaps *maps, struct slot_mapping *map);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* initialize the entire map collection */</span><br><span style="color: hsl(120, 100%, 40%);">+struct slotmaps *slotmap_init(void *ctx);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13177">change 13177</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13177"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-remsim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I0ca7feaa38dfd0468814ef5a1eff997ce854cedf </div>
<div style="display:none"> Gerrit-Change-Number: 13177 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>