blob: 116fd69c186e3292984d636e10faa8e26fd18547 [file] [log] [blame]
Harald Welte77911b02018-08-14 23:47:30 +02001
2#include <stdint.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include <errno.h>
6
7#include <pthread.h>
8
9#include <talloc.h>
10
11#include <osmocom/core/linuxlist.h>
12
13#include "bankd.h"
14
15/* thread-safe lookup of map by client:slot */
16struct bankd_slot_mapping *bankd_slotmap_by_client(struct bankd *bankd, const struct client_slot *client)
17{
18 struct bankd_slot_mapping *map;
19
20 pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);
21 llist_for_each_entry(map, &bankd->slot_mappings, list) {
22 if (client_slot_equals(&map->client, client)) {
23 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
24 return map;
25 }
26 }
27 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
28 return NULL;
29}
30
31/* thread-safe lookup of map by bank:slot */
32struct bankd_slot_mapping *bankd_slotmap_by_bank(struct bankd *bankd, const struct bank_slot *bank)
33{
34 struct bankd_slot_mapping *map;
35
36 pthread_rwlock_rdlock(&bankd->slot_mappings_rwlock);
37 llist_for_each_entry(map, &bankd->slot_mappings, list) {
38 if (bank_slot_equals(&map->bank, bank)) {
39 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
40 return map;
41 }
42 }
43 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
44 return NULL;
45
46}
47
48/* thread-safe creating of a new bank<->client map */
49int bankd_slotmap_add(struct bankd *bankd, const struct bank_slot *bank, const struct client_slot *client)
50{
51 struct bankd_slot_mapping *map;
52
53 /* We assume a single thread (main thread) will ever update the mappings,
54 * and hence we don't have any races by first grabbing + releasing the read
55 * lock twice before grabbing the writelock below */
56
57 map = bankd_slotmap_by_bank(bankd, bank);
58 if (map) {
59 fprintf(stderr, "BANKD %u:%u already in use, cannot add new map\n",
60 bank->bank_id, bank->slot_nr);
61 return -EBUSY;
62 }
63
64 map = bankd_slotmap_by_client(bankd, client);
65 if (map) {
66 fprintf(stderr, "CLIENT %u:%u already in use, cannot add new map\n",
67 client->client_id, client->slot_nr);
68 return -EBUSY;
69 }
70
71 /* allocate new mapping and add to list of mappings */
72 map = talloc_zero(bankd, struct bankd_slot_mapping);
73 if (!map)
74 return -ENOMEM;
75
76 map->bank = *bank;
77 map->client = *client;
78
79 pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);
80 llist_add_tail(&map->list, &bankd->slot_mappings);
81 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
82
Harald Welte12669522018-09-23 19:26:09 +020083 printf("Added Slot Map C(%u:%u) <-> B(%u:%u)\n",
Harald Welte77911b02018-08-14 23:47:30 +020084 map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);
85
86 return 0;
87}
88
89/* thread-safe removal of a bank<->client map */
90void bankd_slotmap_del(struct bankd *bankd, struct bankd_slot_mapping *map)
91{
Harald Welte12669522018-09-23 19:26:09 +020092 printf("Deleting Slot Map C(%u:%u) <-> B(%u:%u)\n",
Harald Welte77911b02018-08-14 23:47:30 +020093 map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);
94
95 pthread_rwlock_wrlock(&bankd->slot_mappings_rwlock);
96 llist_del(&map->list);
97 pthread_rwlock_unlock(&bankd->slot_mappings_rwlock);
98
99 talloc_free(map);
100}