generalize slotmap to make use of it outside of bankd

Change-Id: I0ca7feaa38dfd0468814ef5a1eff997ce854cedf
This commit is contained in:
Harald Welte 2019-03-03 19:02:38 +01:00
parent 61d98e9f3e
commit cbd18960e7
5 changed files with 105 additions and 84 deletions

View File

@ -12,7 +12,7 @@ libosmo_rspro_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \
rspro/libosmo-asn1-rspro.la
libosmo_rspro_la_SOURCES = rspro_util.c
noinst_HEADERS = debug.h bankd.h client.h internal.h rspro_util.h \
noinst_HEADERS = debug.h bankd.h client.h internal.h rspro_util.h slotmap.h \
simtrace2/apdu_dispatch.h \
simtrace2/libusb_util.h \
simtrace2/simtrace2-discovery.h \
@ -25,7 +25,7 @@ pcsc_test_SOURCES = driver_core.c driver_pcsc.c main.c
pcsc_test_LDADD = $(OSMOCORE_LIBS) \
$(PCSC_LIBS) libosmo-rspro.la
remsim_bankd_SOURCES = bankd_slotmap.c bankd_main.c bankd_pcsc.c debug.c
remsim_bankd_SOURCES = slotmap.c bankd_main.c bankd_pcsc.c debug.c
remsim_bankd_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) \
$(PCSC_LIBS) libosmo-rspro.la -lcsv

View File

@ -13,60 +13,11 @@
#include <osmocom/core/linuxlist.h>
#include "rspro_util.h"
#include "slotmap.h"
#include "debug.h"
struct bankd;
struct bank_slot {
uint16_t bank_id;
uint16_t slot_nr;
};
static inline bool bank_slot_equals(const struct bank_slot *a, const struct bank_slot *b)
{
if (a->bank_id == b->bank_id && a->slot_nr == b->slot_nr)
return true;
else
return false;
}
struct client_slot {
uint16_t client_id;
uint16_t slot_nr;
};
static inline bool client_slot_equals(const struct client_slot *a, const struct client_slot *b)
{
if (a->client_id == b->client_id && a->slot_nr == b->slot_nr)
return true;
else
return false;
}
/* slot mappings are created / removed by the server */
struct bankd_slot_mapping {
/* global lits of bankd slot mappings */
struct llist_head list;
/* slot on bank side */
struct bank_slot bank;
/* slot on client side */
struct client_slot client;
};
/* thread-safe lookup of map by client:slot */
struct bankd_slot_mapping *bankd_slotmap_by_client(struct bankd *bankd,
const struct client_slot *client);
/* thread-safe lookup of map by bank:slot */
struct bankd_slot_mapping *bankd_slotmap_by_bank(struct bankd *bankd, const struct bank_slot *bank);
/* thread-safe creating of a new bank<->client map */
int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank,
const struct client_slot *client);
/* thread-safe removal of a bank<->client map */
void bankd_slotmap_del(struct bankd *bankd, struct bankd_slot_mapping *map);
enum bankd_worker_state {
/* just started*/
BW_ST_INIT,
@ -138,9 +89,8 @@ struct bankd {
/* TCP socket at which we are listening */
int accept_fd;
/* list of slit mappings. only ever modified in main thread! */
struct llist_head slot_mappings;
pthread_rwlock_t slot_mappings_rwlock;
/* list of slot mappings. only ever modified in main thread! */
struct slotmaps *slotmaps;
/* list of bankd_workers. accessed/modified by multiple threads; protected by mutex */
struct llist_head workers;

View File

@ -47,8 +47,7 @@ static void bankd_init(struct bankd *bankd)
asn_debug = 0;
/* intialize members of 'bankd' */
INIT_LLIST_HEAD(&bankd->slot_mappings);
pthread_rwlock_init(&bankd->slot_mappings_rwlock, NULL);
bankd->slotmaps = slotmap_init(bankd);
INIT_LLIST_HEAD(&bankd->workers);
pthread_mutex_init(&bankd->workers_mutex, NULL);
@ -71,7 +70,7 @@ static void bankd_init(struct bankd *bankd)
int i;
for (i = 0; i < 5; i++) {
bs.slot_nr = cs.slot_nr = i;
bankd_slotmap_add(bankd, &bs, &cs);
slotmap_add(bankd->slotmaps, &bs, &cs);
}
}
}
@ -304,9 +303,9 @@ static int worker_send_rspro(struct bankd_worker *worker, RsproPDU_t *pdu)
/* attempt to obtain slot-map */
static int worker_try_slotmap(struct bankd_worker *worker)
{
struct bankd_slot_mapping *slmap;
struct slot_mapping *slmap;
slmap = bankd_slotmap_by_client(worker->bankd, &worker->client.clslot);
slmap = slotmap_by_client(worker->bankd->slotmaps, &worker->client.clslot);
if (!slmap) {
LOGW(worker, "No slotmap (yet) for client C(%u:%u)\n",
worker->client.clslot.client_id, worker->client.clslot.slot_nr);

View File

@ -10,58 +10,58 @@
#include <osmocom/core/linuxlist.h>
#include "bankd.h"
#include "slotmap.h"
/* thread-safe lookup of map by client:slot */
struct bankd_slot_mapping *bankd_slotmap_by_client(struct bankd *bankd, const struct client_slot *client)
struct slot_mapping *slotmap_by_client(struct slotmaps *maps, const struct client_slot *client)
{
struct bankd_slot_mapping *map;
struct slot_mapping *map;
pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);
llist_for_each_entry(map, &bankd->slot_mappings, list) {
pthread_rwlock_rdlock(&maps->rwlock);
llist_for_each_entry(map, &maps->mappings, list) {
if (client_slot_equals(&map->client, client)) {
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_unlock(&maps->rwlock);
return map;
}
}
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_unlock(&maps->rwlock);
return NULL;
}
/* thread-safe lookup of map by bank:slot */
struct bankd_slot_mapping *bankd_slotmap_by_bank(struct bankd *bankd, const struct bank_slot *bank)
struct slot_mapping *slotmap_by_bank(struct slotmaps *maps, const struct bank_slot *bank)
{
struct bankd_slot_mapping *map;
struct slot_mapping *map;
pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);
llist_for_each_entry(map, &bankd->slot_mappings, list) {
pthread_rwlock_rdlock(&maps->rwlock);
llist_for_each_entry(map, &maps->mappings, list) {
if (bank_slot_equals(&map->bank, bank)) {
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_unlock(&maps->rwlock);
return map;
}
}
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_unlock(&maps->rwlock);
return NULL;
}
/* thread-safe creating of a new bank<->client map */
int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank, const struct client_slot *client)
int slotmap_add(struct slotmaps *maps, const struct bank_slot *bank, const struct client_slot *client)
{
struct bankd_slot_mapping *map;
struct slot_mapping *map;
/* We assume a single thread (main thread) will ever update the mappings,
* and hence we don't have any races by first grabbing + releasing the read
* lock twice before grabbing the writelock below */
map = bankd_slotmap_by_bank(bankd, bank);
map = slotmap_by_bank(maps, bank);
if (map) {
fprintf(stderr, "BANKD %u:%u already in use, cannot add new map\n",
bank->bank_id, bank->slot_nr);
return -EBUSY;
}
map = bankd_slotmap_by_client(bankd, client);
map = slotmap_by_client(maps, client);
if (map) {
fprintf(stderr, "CLIENT %u:%u already in use, cannot add new map\n",
client->client_id, client->slot_nr);
@ -69,16 +69,16 @@ int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank, const s
}
/* allocate new mapping and add to list of mappings */
map = talloc_zero(bankd, struct bankd_slot_mapping);
map = talloc_zero(maps, struct slot_mapping);
if (!map)
return -ENOMEM;
map->bank = *bank;
map->client = *client;
pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);
llist_add_tail(&map->list, &bankd->slot_mappings);
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_wrlock(&maps->rwlock);
llist_add_tail(&map->list, &maps->mappings);
pthread_rwlock_unlock(&maps->rwlock);
printf("Added Slot Map C(%u:%u) <-> B(%u:%u)\n",
map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);
@ -87,14 +87,24 @@ int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank, const s
}
/* thread-safe removal of a bank<->client map */
void bankd_slotmap_del(struct bankd *bankd, struct bankd_slot_mapping *map)
void slotmap_del(struct slotmaps *maps, struct slot_mapping *map)
{
printf("Deleting Slot Map C(%u:%u) <-> B(%u:%u)\n",
map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);
pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_wrlock(&maps->rwlock);
llist_del(&map->list);
pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
pthread_rwlock_unlock(&maps->rwlock);
talloc_free(map);
}
struct slotmaps *slotmap_init(void *ctx)
{
struct slotmaps *sm = talloc_zero(ctx, struct slotmaps);
INIT_LLIST_HEAD(&sm->mappings);
pthread_rwlock_init(&sm->rwlock, NULL);
return sm;
}

62
src/slotmap.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include <osmocom/core/linuxlist.h>
struct bank_slot {
uint16_t bank_id;
uint16_t slot_nr;
};
static inline bool bank_slot_equals(const struct bank_slot *a, const struct bank_slot *b)
{
if (a->bank_id == b->bank_id && a->slot_nr == b->slot_nr)
return true;
else
return false;
}
struct client_slot {
uint16_t client_id;
uint16_t slot_nr;
};
static inline bool client_slot_equals(const struct client_slot *a, const struct client_slot *b)
{
if (a->client_id == b->client_id && a->slot_nr == b->slot_nr)
return true;
else
return false;
}
/* slot mappings are created / removed by the server */
struct slot_mapping {
/* global lits of bankd slot mappings */
struct llist_head list;
/* slot on bank side */
struct bank_slot bank;
/* slot on client side */
struct client_slot client;
};
/* collection of slot mappings */
struct slotmaps {
struct llist_head mappings;
pthread_rwlock_t rwlock;
};
/* thread-safe lookup of map by client:slot */
struct slot_mapping *slotmap_by_client(struct slotmaps *maps, const struct client_slot *client);
/* thread-safe lookup of map by bank:slot */
struct slot_mapping *slotmap_by_bank(struct slotmaps *maps, const struct bank_slot *bank);
/* thread-safe creating of a new bank<->client map */
int slotmap_add(struct slotmaps *maps, const struct bank_slot *bank, const struct client_slot *client);
/* thread-safe removal of a bank<->client map */
void slotmap_del(struct slotmaps *maps, struct slot_mapping *map);
/* initialize the entire map collection */
struct slotmaps *slotmap_init(void *ctx);