blob: 303f5fda90fc28671af6898afd3ae4474cf7c1ee [file] [log] [blame]
Harald Weltecbd18962019-03-03 19:02:38 +01001
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 "slotmap.h"
14
15/* thread-safe lookup of map by client:slot */
16struct slot_mapping *slotmap_by_client(struct slotmaps *maps, const struct client_slot *client)
17{
18 struct slot_mapping *map;
19
20 pthread_rwlock_rdlock(&maps->rwlock);
21 llist_for_each_entry(map, &maps->mappings, list) {
22 if (client_slot_equals(&map->client, client)) {
23 pthread_rwlock_unlock(&maps->rwlock);
24 return map;
25 }
26 }
27 pthread_rwlock_unlock(&maps->rwlock);
28 return NULL;
29}
30
31/* thread-safe lookup of map by bank:slot */
32struct slot_mapping *slotmap_by_bank(struct slotmaps *maps, const struct bank_slot *bank)
33{
34 struct slot_mapping *map;
35
36 pthread_rwlock_rdlock(&maps->rwlock);
37 llist_for_each_entry(map, &maps->mappings, list) {
38 if (bank_slot_equals(&map->bank, bank)) {
39 pthread_rwlock_unlock(&maps->rwlock);
40 return map;
41 }
42 }
43 pthread_rwlock_unlock(&maps->rwlock);
44 return NULL;
45
46}
47
48/* thread-safe creating of a new bank<->client map */
49int slotmap_add(struct slotmaps *maps, const struct bank_slot *bank, const struct client_slot *client)
50{
51 struct 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 = slotmap_by_bank(maps, 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 = slotmap_by_client(maps, 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(maps, struct slot_mapping);
73 if (!map)
74 return -ENOMEM;
75
76 map->bank = *bank;
77 map->client = *client;
78
79 pthread_rwlock_wrlock(&maps->rwlock);
80 llist_add_tail(&map->list, &maps->mappings);
81 pthread_rwlock_unlock(&maps->rwlock);
82
83 printf("Added Slot Map C(%u:%u) <-> B(%u:%u)\n",
84 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 slotmap_del(struct slotmaps *maps, struct slot_mapping *map)
91{
92 printf("Deleting Slot Map C(%u:%u) <-> B(%u:%u)\n",
93 map->client.client_id, map->client.slot_nr, map->bank.bank_id, map->bank.slot_nr);
94
95 pthread_rwlock_wrlock(&maps->rwlock);
96 llist_del(&map->list);
97 pthread_rwlock_unlock(&maps->rwlock);
98
99 talloc_free(map);
100}
101
102struct slotmaps *slotmap_init(void *ctx)
103{
104 struct slotmaps *sm = talloc_zero(ctx, struct slotmaps);
105
106 INIT_LLIST_HEAD(&sm->mappings);
107 pthread_rwlock_init(&sm->rwlock, NULL);
108
109 return sm;
110}