TAS
TCP Acceleration as an OS Service
packetmem.c
1 /*
2  * Copyright 2019 University of Washington, Max Planck Institute for
3  * Software Systems, and The University of Texas at Austin
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include <tas.h>
29 #include "internal.h"
30 
32  uintptr_t base;
33  size_t len;
34 
35  struct packetmem_handle *next;
36 };
37 
38 static inline struct packetmem_handle *ph_alloc(void);
39 static inline void ph_free(struct packetmem_handle *ph);
40 static inline void merge_items(struct packetmem_handle *ph_prev);
41 
42 static struct packetmem_handle *freelist;
43 
44 int packetmem_init(void)
45 {
46  struct packetmem_handle *ph;
47 
48  if ((ph = ph_alloc()) == NULL) {
49  fprintf(stderr, "packetmem_init: ph_alloc failed\n");
50  return -1;
51  }
52 
53  ph->base = 0;
54  ph->len = tas_info->dma_mem_size;
55  ph->next = NULL;
56  freelist = ph;
57 
58  return 0;
59 }
60 
61 int packetmem_alloc(size_t length, uintptr_t *off,
62  struct packetmem_handle **handle)
63 {
64  struct packetmem_handle *ph, *ph_prev, *ph_new;
65 
66  /* look for first fit */
67  ph_prev = NULL;
68  ph = freelist;
69  while (ph != NULL && ph->len < length) {
70  ph_prev = ph;
71  ph = ph->next;
72  }
73 
74  /* didn't find a fit */
75  if (ph == NULL) {
76  return -1;
77  }
78 
79  if (ph->len == length) {
80  /* simple case, don't need to split this handle */
81 
82  /* pointer to previous next pointer for removal */
83  if (ph_prev == NULL) {
84  freelist = ph->next;
85  } else {
86  ph_prev->next = ph->next;
87  }
88 
89  ph_new = ph;
90  } else {
91  /* need to split */
92 
93  /* new packetmem handle for splitting */
94  if ((ph_new = ph_alloc()) == NULL) {
95  fprintf(stderr, "packetmem_alloc: ph_alloc failed\n");
96  return -1;
97  }
98 
99  ph_new->base = ph->base;
100  ph_new->len = length;
101  ph_new->next = NULL;
102 
103  ph->base += length;
104  ph->len -= length;
105  }
106 
107  *handle = ph_new;
108  *off = ph_new->base;
109 
110  return 0;
111 }
112 
113 void packetmem_free(struct packetmem_handle *handle)
114 {
115  struct packetmem_handle *ph, *ph_prev;
116 
117  /* look for first successor */
118  ph_prev = NULL;
119  ph = freelist;
120  while (ph != NULL && ph->next != NULL && ph->next->base < handle->base) {
121  ph_prev = ph;
122  ph = ph->next;
123  }
124 
125  /* add to list */
126  if (ph_prev == NULL) {
127  handle->next = freelist;
128  freelist = handle;
129  } else {
130  handle->next = ph_prev->next;
131  ph_prev->next = handle;
132  }
133 
134  /* merge items if necessary */
135  merge_items(ph_prev);
136 }
137 
141 static inline void merge_items(struct packetmem_handle *ph_prev)
142 {
143  struct packetmem_handle *ph, *ph_next;
144 
145  /* try to merge with predecessor if there is one */
146  if (ph_prev != NULL) {
147  ph = ph_prev->next;
148  if (ph_prev->base + ph_prev->len == ph->base) {
149  /* merge with predecessor */
150  ph_prev->next = ph->next;
151  ph_prev->len += ph->len;
152  ph_free(ph);
153  ph = ph_prev;
154  }
155  } else {
156  ph = freelist;
157  }
158 
159  /* try to merge with successor if there is one */
160  ph_next = ph->next;
161  if (ph_next != NULL && ph->base + ph->len == ph_next->base) {
162  ph->len += ph_next->len;
163  ph->next = ph_next->next;
164  ph_free(ph_next);
165  }
166 }
167 
168 static inline struct packetmem_handle *ph_alloc(void)
169 {
170  return malloc(sizeof(struct packetmem_handle));
171 }
172 
173 static inline void ph_free(struct packetmem_handle *ph)
174 {
175  free(ph);
176 }
int packetmem_init(void)
Definition: packetmem.c:44
int packetmem_alloc(size_t length, uintptr_t *off, struct packetmem_handle **handle)
Definition: packetmem.c:61
void packetmem_free(struct packetmem_handle *handle)
Definition: packetmem.c:113
uint64_t dma_mem_size
Definition: tas_memif.h:60