man: minor: astraceroute: add .PPs
[netsniff-ng.git] / cpusched.c
blob13ed9a7c4bb453783a9a0c65610f49d021885909
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #define _GNU_SOURCE
8 #include <search.h>
9 #include <limits.h>
10 #include <errno.h>
11 #include <string.h>
13 #include "locking.h"
14 #include "cpusched.h"
15 #include "xmalloc.h"
16 #include "hash.h"
18 struct map_entry {
19 int fd;
20 unsigned int cpu;
21 struct map_entry *next;
24 static struct hash_table mapper;
26 static unsigned int *cpu_assigned = NULL;
28 static unsigned int cpu_len = 0;
30 static struct rwlock map_lock;
32 void init_cpusched(unsigned int cpus)
34 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;
159 while ((next = e->next)) {
160 e->next = NULL;
161 xfree(e);
162 e = next;
165 xfree(e);
166 return 0;
169 void destroy_cpusched(void)
171 rwlock_wr_lock(&map_lock);
173 xfree(cpu_assigned);
174 cpu_len = 0;
175 for_each_hash(&mapper, cleanup_batch);
176 free_hash(&mapper);
178 rwlock_unlock(&map_lock);
179 rwlock_destroy(&map_lock);