curvetun: adapt shell scripts to use environment
[netsniff-ng.git] / src / ct_cpusched.c
blob4d3dda2a4b806b6ff6b2bc436ed7c444c588e514
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
9 #include <search.h>
10 #include <limits.h>
11 #include <errno.h>
12 #include <string.h>
14 #include "locking.h"
15 #include "ct_cpusched.h"
16 #include "xmalloc.h"
17 #include "hash.h"
19 /* Flow to CPU mapper / scheduler to keep connection CPU-local */
20 struct map_entry {
21 int fd;
22 unsigned int cpu;
23 struct map_entry *next;
26 static struct hash_table mapper;
27 static unsigned int *cpu_assigned = NULL;
28 static unsigned int cpu_len = 0;
29 static struct rwlock map_lock;
31 void init_cpusched(unsigned int cpus)
33 rwlock_init(&map_lock);
35 rwlock_wr_lock(&map_lock);
37 cpu_len = cpus;
38 cpu_assigned = xzmalloc(cpus * sizeof(*cpu_assigned));
40 memset(&mapper, 0, sizeof(mapper));
41 init_hash(&mapper);
43 rwlock_unlock(&map_lock);
46 static int get_appropriate_cpu(void)
48 int i, cpu = 0;
49 int work = INT_MAX;
51 for (i = 0; i < cpu_len; ++i) {
52 if (cpu_assigned[i] < work) {
53 work = cpu_assigned[i];
54 cpu = i;
58 return cpu;
61 unsigned int socket_to_cpu(int fd)
63 int cpu = 0;
64 struct map_entry *entry;
66 errno = 0;
68 rwlock_rd_lock(&map_lock);
70 entry = lookup_hash(fd, &mapper);
71 while (entry && fd != entry->fd)
72 entry = entry->next;
73 if (entry && fd == entry->fd)
74 cpu = entry->cpu;
75 else
76 errno = ENOENT;
78 rwlock_unlock(&map_lock);
80 return cpu;
83 unsigned int register_socket(int fd)
85 void **pos;
86 struct map_entry *entry;
88 rwlock_wr_lock(&map_lock);
90 entry = xzmalloc(sizeof(*entry));
91 entry->fd = fd;
92 entry->cpu = get_appropriate_cpu();
94 cpu_assigned[entry->cpu]++;
96 pos = insert_hash(entry->fd, entry, &mapper);
97 if (pos) {
98 entry->next = (*pos);
99 (*pos) = entry;
102 rwlock_unlock(&map_lock);
104 return entry->cpu;
107 static struct map_entry *socket_to_map_entry(int fd)
109 struct map_entry *entry, *ret = NULL;
111 errno = 0;
113 rwlock_rd_lock(&map_lock);
115 entry = lookup_hash(fd, &mapper);
116 while (entry && fd != entry->fd)
117 entry = entry->next;
118 if (entry && fd == entry->fd)
119 ret = entry;
120 else
121 errno = ENOENT;
123 rwlock_unlock(&map_lock);
125 return ret;
128 void unregister_socket(int fd)
130 struct map_entry *pos;
131 struct map_entry *entry = socket_to_map_entry(fd);
133 if (!entry == 0 && errno == ENOENT)
134 return;
136 rwlock_wr_lock(&map_lock);
138 cpu_assigned[entry->cpu]--;
140 pos = remove_hash(entry->fd, entry, entry->next, &mapper);
141 while (pos && pos->next && pos->next != entry)
142 pos = pos->next;
143 if (pos && pos->next && pos->next == entry)
144 pos->next = entry->next;
146 entry->next = NULL;
147 xfree(entry);
149 rwlock_unlock(&map_lock);
152 static int cleanup_batch(void *ptr)
154 struct map_entry *next;
155 struct map_entry *e = ptr;
157 if (!e)
158 return 0;
160 while ((next = e->next)) {
161 e->next = NULL;
162 xfree(e);
163 e = next;
166 xfree(e);
168 return 0;
171 void destroy_cpusched(void)
173 rwlock_wr_lock(&map_lock);
175 xfree(cpu_assigned);
176 cpu_len = 0;
177 for_each_hash(&mapper, cleanup_batch);
178 free_hash(&mapper);
180 rwlock_unlock(&map_lock);
182 rwlock_destroy(&map_lock);