Changes in uspace/lib/packet/generic/packet_server.c [f63a591d:376a7fd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/packet/generic/packet_server.c
rf63a591d r376a7fd 27 27 */ 28 28 29 /** @addtogroup packet29 /** @addtogroup libpacket 30 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * Packet server implementation. 35 */ 34 * Packet server implementation. 35 */ 36 37 #include <packet_server.h> 38 #include <packet_local.h> 36 39 37 40 #include <align.h> … … 51 54 #include <net/packet_header.h> 52 55 53 #include <packet_server.h>54 #include <packet_local.h>55 56 56 #define FREE_QUEUES_COUNT 7 57 57 58 /** The default address length reserved for new packets. 59 */ 58 /** The default address length reserved for new packets. */ 60 59 #define DEFAULT_ADDR_LEN 32 61 60 62 /** The default prefix reserved for new packets. 63 */ 61 /** The default prefix reserved for new packets. */ 64 62 #define DEFAULT_PREFIX 64 65 63 66 /** The default suffix reserved for new packets. 67 */ 64 /** The default suffix reserved for new packets. */ 68 65 #define DEFAULT_SUFFIX 64 69 66 70 /** Packet server global data. 71 */ 72 static struct{ 73 /** Safety lock. 74 */ 67 /** Packet server global data. */ 68 static struct { 69 /** Safety lock. */ 75 70 fibril_mutex_t lock; 76 /** Free packet queues. 77 */ 71 /** Free packet queues. */ 78 72 packet_t free[FREE_QUEUES_COUNT]; 79 /** Packet length upper bounds of the free packet queues. 80 * The maximal lengths of packets in each queue in the ascending order. 81 * The last queue is not limited. 73 74 /** 75 * Packet length upper bounds of the free packet queues. The maximal 76 * lengths of packets in each queue in the ascending order. The last 77 * queue is not limited. 82 78 */ 83 79 size_t sizes[FREE_QUEUES_COUNT]; 84 /** Total packets allocated.85 */80 81 /** Total packets allocated. */ 86 82 unsigned int count; 87 83 } ps_globals = { 88 84 .lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock), 89 .free = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}, 90 .sizes = {PAGE_SIZE, PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, PAGE_SIZE * 16, PAGE_SIZE * 32, PAGE_SIZE * 64}, 85 .free = { 86 NULL, 87 NULL, 88 NULL, 89 NULL, 90 NULL, 91 NULL, 92 NULL 93 }, 94 .sizes = { 95 PAGE_SIZE, 96 PAGE_SIZE * 2, 97 PAGE_SIZE * 4, 98 PAGE_SIZE * 8, 99 PAGE_SIZE * 16, 100 PAGE_SIZE * 32, 101 PAGE_SIZE * 64 102 }, 91 103 .count = 0 92 104 }; … … 102 114 103 115 /** Clears and initializes the packet according to the given dimensions. 104 * @param[in] packet The packet to be initialized. 105 * @param[in] addr_len The source and destination addresses maximal length in bytes. 106 * @param[in] max_prefix The maximal prefix length in bytes. 107 * @param[in] max_content The maximal content length in bytes. 108 * @param[in] max_suffix The maximal suffix length in bytes. 109 */ 110 static void packet_init(packet_t packet, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix){ 116 * 117 * @param[in] packet The packet to be initialized. 118 * @param[in] addr_len The source and destination addresses maximal length in 119 * bytes. 120 * @param[in] max_prefix The maximal prefix length in bytes. 121 * @param[in] max_content The maximal content length in bytes. 122 * @param[in] max_suffix The maximal suffix length in bytes. 123 */ 124 static void 125 packet_init(packet_t packet, size_t addr_len, size_t max_prefix, 126 size_t max_content, size_t max_suffix) 127 { 111 128 // clear the packet content 112 bzero(((void *) packet) + sizeof(struct packet), packet->length - sizeof(struct packet)); 129 bzero(((void *) packet) + sizeof(struct packet), 130 packet->length - sizeof(struct packet)); 131 113 132 // clear the packet header 114 133 packet->order = 0; … … 125 144 } 126 145 127 /** Creates a new packet of dimensions at least as given. 128 * Should be used only when the global data are locked. 129 * @param[in] length The total length of the packet, including the header, the addresses and the data of the packet. 130 * @param[in] addr_len The source and destination addresses maximal length in bytes. 131 * @param[in] max_prefix The maximal prefix length in bytes. 132 * @param[in] max_content The maximal content length in bytes. 133 * @param[in] max_suffix The maximal suffix length in bytes. 134 * @returns The packet of dimensions at least as given. 135 * @returns NULL if there is not enough memory left. 136 */ 137 static packet_t packet_create(size_t length, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix){ 146 /** Creates a new packet of dimensions at least as given. 147 * 148 * Should be used only when the global data are locked. 149 * 150 * @param[in] length The total length of the packet, including the header, 151 * the addresses and the data of the packet. 152 * @param[in] addr_len The source and destination addresses maximal length in 153 * bytes. 154 * @param[in] max_prefix The maximal prefix length in bytes. 155 * @param[in] max_content The maximal content length in bytes. 156 * @param[in] max_suffix The maximal suffix length in bytes. 157 * @returns The packet of dimensions at least as given. 158 * @returns NULL if there is not enough memory left. 159 */ 160 static packet_t 161 packet_create(size_t length, size_t addr_len, size_t max_prefix, 162 size_t max_content, size_t max_suffix) 163 { 138 164 ERROR_DECLARE; 139 165 … … 141 167 142 168 // already locked 143 packet = (packet_t) mmap(NULL, length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); 144 if(packet == MAP_FAILED){ 169 packet = (packet_t) mmap(NULL, length, PROTO_READ | PROTO_WRITE, 170 MAP_SHARED | MAP_ANONYMOUS, 0, 0); 171 if (packet == MAP_FAILED) 145 172 return NULL; 146 } 147 ++ ps_globals.count;173 174 ps_globals.count++; 148 175 packet->packet_id = ps_globals.count; 149 176 packet->length = length; 150 177 packet_init(packet, addr_len, max_prefix, max_content, max_suffix); 151 178 packet->magic_value = PACKET_MAGIC_VALUE; 152 if (ERROR_OCCURRED(pm_add(packet))){179 if (ERROR_OCCURRED(pm_add(packet))) { 153 180 munmap(packet, packet->length); 154 181 return NULL; 155 182 } 183 156 184 return packet; 157 185 } … … 163 191 * Lock the global data during its processing. 164 192 * 165 * @param[in] addr_len The source and destination addresses166 * maximal length inbytes.167 * @param[in] max_prefix 193 * @param[in] addr_len The source and destination addresses maximal length in 194 * bytes. 195 * @param[in] max_prefix The maximal prefix length in bytes. 168 196 * @param[in] max_content The maximal content length in bytes. 169 * @param[in] max_suffix The maximal suffix length in bytes. 170 * 171 * @return The packet of dimensions at least as given. 172 * @return NULL if there is not enough memory left. 173 * 174 */ 175 static packet_t packet_get_local(size_t addr_len, size_t max_prefix, 176 size_t max_content, size_t max_suffix) 177 { 178 size_t length = ALIGN_UP(sizeof(struct packet) + 2 * addr_len + max_prefix 179 + max_content + max_suffix, PAGE_SIZE); 197 * @param[in] max_suffix The maximal suffix length in bytes. 198 * @return The packet of dimensions at least as given. 199 * @return NULL if there is not enough memory left. 200 */ 201 static packet_t 202 packet_get_local(size_t addr_len, size_t max_prefix, size_t max_content, 203 size_t max_suffix) 204 { 205 size_t length = ALIGN_UP(sizeof(struct packet) + 2 * addr_len + 206 max_prefix + max_content + max_suffix, PAGE_SIZE); 180 207 181 208 fibril_mutex_lock(&ps_globals.lock); … … 184 211 unsigned int index; 185 212 186 for (index = 0; index < FREE_QUEUES_COUNT - 1; index++) { 187 if (length <= ps_globals.sizes[index]) { 188 packet = ps_globals.free[index]; 213 for (index = 0; index < FREE_QUEUES_COUNT; index++) { 214 if ((length > ps_globals.sizes[index]) && 215 (index < FREE_QUEUES_COUNT - 1)) 216 continue; 217 218 packet = ps_globals.free[index]; 219 while (packet_is_valid(packet) && (packet->length < length)) 220 packet = pm_find(packet->next); 221 222 if (packet_is_valid(packet)) { 223 if (packet == ps_globals.free[index]) 224 ps_globals.free[index] = pq_detach(packet); 225 else 226 pq_detach(packet); 189 227 190 while (packet_is_valid(packet) && (packet->length < length)) 191 packet = pm_find(packet->next); 228 packet_init(packet, addr_len, max_prefix, max_content, 229 max_suffix); 230 fibril_mutex_unlock(&ps_globals.lock); 192 231 193 if (packet_is_valid(packet)) { 194 if (packet == ps_globals.free[index]) 195 ps_globals.free[index] = pq_detach(packet); 196 else 197 pq_detach(packet); 198 199 packet_init(packet, addr_len, max_prefix, max_content, 200 max_suffix); 201 fibril_mutex_unlock(&ps_globals.lock); 202 203 return packet; 204 } 232 return packet; 205 233 } 206 234 } … … 228 256 /** Release the packet and returns it to the appropriate free packet queue. 229 257 * 230 * Should be used only when the global data are locked. 231 * 232 * @param[in] packet The packet to be released. 233 * 234 */ 235 static void packet_release(packet_t packet){ 258 * Should be used only when the global data are locked. 259 * 260 * @param[in] packet The packet to be released. 261 * 262 */ 263 static void packet_release(packet_t packet) 264 { 236 265 int index; 237 266 int result; 238 267 239 // remove debug dump 240 // printf("packet %d released\n", packet->packet_id); 241 for(index = 0; (index < FREE_QUEUES_COUNT - 1) && (packet->length > ps_globals.sizes[index]); ++ index); 242 result = pq_add(&ps_globals.free[index], packet, packet->length, packet->length); 268 for (index = 0; (index < FREE_QUEUES_COUNT - 1) && 269 (packet->length > ps_globals.sizes[index]); index++) { 270 ; 271 } 272 273 result = pq_add(&ps_globals.free[index], packet, packet->length, 274 packet->length); 243 275 assert(result == EOK); 244 276 } 245 277 246 278 /** Releases the packet queue. 247 * @param[in] packet_id The first packet identifier. 248 * @returns EOK on success. 249 * @returns ENOENT if there is no such packet. 250 */ 251 static int packet_release_wrapper(packet_id_t packet_id){ 279 * 280 * @param[in] packet_id The first packet identifier. 281 * @returns EOK on success. 282 * @returns ENOENT if there is no such packet. 283 */ 284 static int packet_release_wrapper(packet_id_t packet_id) 285 { 252 286 packet_t packet; 253 287 254 288 packet = pm_find(packet_id); 255 if (! packet_is_valid(packet)){289 if (!packet_is_valid(packet)) 256 290 return ENOENT; 257 } 291 258 292 fibril_mutex_lock(&ps_globals.lock); 259 293 pq_destroy(packet, packet_release); 260 294 fibril_mutex_unlock(&ps_globals.lock); 295 261 296 return EOK; 262 297 } … … 268 303 269 304 /** Shares the packet memory block. 270 * @param[in] packet The packet to be shared. 271 * @returns EOK on success. 272 * @returns EINVAL if the packet is not valid. 273 * @returns EINVAL if the calling module does not accept the memory. 274 * @returns ENOMEM if the desired and actual sizes differ. 275 * @returns Other error codes as defined for the async_share_in_finalize() function. 276 */ 277 static int packet_reply(const packet_t packet){ 305 * @param[in] packet The packet to be shared. 306 * @returns EOK on success. 307 * @returns EINVAL if the packet is not valid. 308 * @returns EINVAL if the calling module does not accept the memory. 309 * @returns ENOMEM if the desired and actual sizes differ. 310 * @returns Other error codes as defined for the 311 * async_share_in_finalize() function. 312 */ 313 static int packet_reply(const packet_t packet) 314 { 278 315 ipc_callid_t callid; 279 316 size_t size; 280 317 281 if (! packet_is_valid(packet)){318 if (!packet_is_valid(packet)) 282 319 return EINVAL; 283 } 284 if(async_share_in_receive(&callid, &size) <= 0) return EINVAL; 285 if(size != packet->length){ 320 321 if (!async_share_in_receive(&callid, &size)) { 322 ipc_answer_0(callid, EINVAL); 323 return EINVAL; 324 } 325 326 if (size != packet->length) { 327 ipc_answer_0(callid, ENOMEM); 286 328 return ENOMEM; 287 329 } 288 return async_share_in_finalize(callid, packet, PROTO_READ | PROTO_WRITE); 289 } 290 291 int packet_server_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 330 331 return async_share_in_finalize(callid, packet, 332 PROTO_READ | PROTO_WRITE); 333 } 334 335 /** Processes the packet server message. 336 * 337 * @param[in] callid The message identifier. 338 * @param[in] call The message parameters. 339 * @param[out] answer The message answer parameters. 340 * @param[out] answer_count The last parameter for the actual answer in the 341 * answer parameter. 342 * @returns EOK on success. 343 * @returns ENOMEM if there is not enough memory left. 344 * @returns ENOENT if there is no such packet as in the packet 345 * message parameter. 346 * @returns ENOTSUP if the message is not known. 347 * @returns Other error codes as defined for the 348 * packet_release_wrapper() function. 349 */ 350 int 351 packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 352 int *answer_count) 353 { 292 354 packet_t packet; 293 355 294 356 *answer_count = 0; 295 switch(IPC_GET_METHOD(*call)){ 296 case IPC_M_PHONE_HUNGUP: 297 return EOK; 298 case NET_PACKET_CREATE_1: 299 packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX, IPC_GET_CONTENT(call), DEFAULT_SUFFIX); 300 if(! packet){ 301 return ENOMEM; 302 } 303 *answer_count = 2; 304 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 305 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 306 return EOK; 307 case NET_PACKET_CREATE_4: 308 packet = packet_get_local(((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ? IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN), DEFAULT_PREFIX + IPC_GET_PREFIX(call), IPC_GET_CONTENT(call), DEFAULT_SUFFIX + IPC_GET_SUFFIX(call)); 309 if(! packet){ 310 return ENOMEM; 311 } 312 *answer_count = 2; 313 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 314 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 315 return EOK; 316 case NET_PACKET_GET: 317 packet = pm_find(IPC_GET_ID(call)); 318 if(! packet_is_valid(packet)){ 319 return ENOENT; 320 } 321 return packet_reply(packet); 322 case NET_PACKET_GET_SIZE: 323 packet = pm_find(IPC_GET_ID(call)); 324 if(! packet_is_valid(packet)){ 325 return ENOENT; 326 } 327 IPC_SET_ARG1(*answer, (ipcarg_t) packet->length); 328 *answer_count = 1; 329 return EOK; 330 case NET_PACKET_RELEASE: 331 return packet_release_wrapper(IPC_GET_ID(call)); 332 } 357 switch (IPC_GET_METHOD(*call)) { 358 case IPC_M_PHONE_HUNGUP: 359 return EOK; 360 361 case NET_PACKET_CREATE_1: 362 packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX, 363 IPC_GET_CONTENT(call), DEFAULT_SUFFIX); 364 if (!packet) 365 return ENOMEM; 366 *answer_count = 2; 367 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 368 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 369 return EOK; 370 371 case NET_PACKET_CREATE_4: 372 packet = packet_get_local( 373 ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ? 374 IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN), 375 DEFAULT_PREFIX + IPC_GET_PREFIX(call), 376 IPC_GET_CONTENT(call), 377 DEFAULT_SUFFIX + IPC_GET_SUFFIX(call)); 378 if (!packet) 379 return ENOMEM; 380 *answer_count = 2; 381 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 382 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 383 return EOK; 384 385 case NET_PACKET_GET: 386 packet = pm_find(IPC_GET_ID(call)); 387 if (!packet_is_valid(packet)) 388 return ENOENT; 389 return packet_reply(packet); 390 391 case NET_PACKET_GET_SIZE: 392 packet = pm_find(IPC_GET_ID(call)); 393 if (!packet_is_valid(packet)) 394 return ENOENT; 395 IPC_SET_ARG1(*answer, (ipcarg_t) packet->length); 396 *answer_count = 1; 397 return EOK; 398 399 case NET_PACKET_RELEASE: 400 return packet_release_wrapper(IPC_GET_ID(call)); 401 } 402 333 403 return ENOTSUP; 334 404 }
Note:
See TracChangeset
for help on using the changeset viewer.