Changeset 515a00da in mainline
- Timestamp:
- 2010-10-24T21:32:54Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 57f737a
- Parents:
- 95e3fd0b
- Location:
- uspace/lib/packet
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/packet/generic/packet_server.c
r95e3fd0b r515a00da 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 } 173 147 174 ++ ps_globals.count; 148 175 packet->packet_id = ps_globals.count; … … 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); … … 185 212 186 213 for (index = 0; index < FREE_QUEUES_COUNT - 1; index++) { 187 if (length <= ps_globals.sizes[index]) { 188 packet = ps_globals.free[index]; 214 if (length > ps_globals.sizes[index]) 215 continue; 216 217 packet = ps_globals.free[index]; 218 while (packet_is_valid(packet) && (packet->length < length)) 219 packet = pm_find(packet->next); 220 221 if (packet_is_valid(packet)) { 222 if (packet == ps_globals.free[index]) 223 ps_globals.free[index] = pq_detach(packet); 224 else 225 pq_detach(packet); 189 226 190 while (packet_is_valid(packet) && (packet->length < length)) 191 packet = pm_find(packet->next); 227 packet_init(packet, addr_len, max_prefix, max_content, 228 max_suffix); 229 fibril_mutex_unlock(&ps_globals.lock); 192 230 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 } 231 return packet; 205 232 } 206 233 } … … 228 255 /** Release the packet and returns it to the appropriate free packet queue. 229 256 * 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){ 257 * Should be used only when the global data are locked. 258 * 259 * @param[in] packet The packet to be released. 260 * 261 */ 262 static void packet_release(packet_t packet) 263 { 236 264 int index; 237 265 int result; 238 266 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); 267 for (index = 0; (index < FREE_QUEUES_COUNT - 1) && 268 (packet->length > ps_globals.sizes[index]); index++) { 269 ; 270 } 271 272 result = pq_add(&ps_globals.free[index], packet, packet->length, 273 packet->length); 243 274 assert(result == EOK); 244 275 } 245 276 246 277 /** 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){ 278 * 279 * @param[in] packet_id The first packet identifier. 280 * @returns EOK on success. 281 * @returns ENOENT if there is no such packet. 282 */ 283 static int packet_release_wrapper(packet_id_t packet_id) 284 { 252 285 packet_t packet; 253 286 254 287 packet = pm_find(packet_id); 255 if (! packet_is_valid(packet)){288 if (!packet_is_valid(packet)) 256 289 return ENOENT; 257 } 290 258 291 fibril_mutex_lock(&ps_globals.lock); 259 292 pq_destroy(packet, packet_release); 260 293 fibril_mutex_unlock(&ps_globals.lock); 294 261 295 return EOK; 262 296 } … … 268 302 269 303 /** 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){ 304 * @param[in] packet The packet to be shared. 305 * @returns EOK on success. 306 * @returns EINVAL if the packet is not valid. 307 * @returns EINVAL if the calling module does not accept the memory. 308 * @returns ENOMEM if the desired and actual sizes differ. 309 * @returns Other error codes as defined for the 310 * async_share_in_finalize() function. 311 */ 312 static int packet_reply(const packet_t packet) 313 { 278 314 ipc_callid_t callid; 279 315 size_t size; 280 316 281 if (! packet_is_valid(packet)){317 if (!packet_is_valid(packet)) 282 318 return EINVAL; 319 320 if (size != packet->length) 321 return ENOMEM; 322 323 if (!async_share_in_receive(&callid, &size)) 324 return EINVAL; 325 326 return async_share_in_finalize(callid, packet, 327 PROTO_READ | PROTO_WRITE); 328 } 329 330 /** Processes the packet server message. 331 * 332 * @param[in] callid The message identifier. 333 * @param[in] call The message parameters. 334 * @param[out] answer The message answer parameters. 335 * @param[out] answer_count The last parameter for the actual answer in the 336 * answer parameter. 337 * @returns EOK on success. 338 * @returns ENOMEM if there is not enough memory left. 339 * @returns ENOENT if there is no such packet as in the packet 340 * message parameter. 341 * @returns ENOTSUP if the message is not known. 342 * @returns Other error codes as defined for the 343 * packet_release_wrapper() function. 344 */ 345 int 346 packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 347 int *answer_count) 348 { 349 packet_t packet; 350 351 *answer_count = 0; 352 switch (IPC_GET_METHOD(*call)) { 353 case IPC_M_PHONE_HUNGUP: 354 return EOK; 355 356 case NET_PACKET_CREATE_1: 357 packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX, 358 IPC_GET_CONTENT(call), DEFAULT_SUFFIX); 359 if (!packet) 360 return ENOMEM; 361 *answer_count = 2; 362 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 363 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 364 return EOK; 365 366 case NET_PACKET_CREATE_4: 367 packet = packet_get_local( 368 ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ? 369 IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN), 370 DEFAULT_PREFIX + IPC_GET_PREFIX(call), 371 IPC_GET_CONTENT(call), 372 DEFAULT_SUFFIX + IPC_GET_SUFFIX(call)); 373 if (!packet) 374 return ENOMEM; 375 *answer_count = 2; 376 IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id); 377 IPC_SET_ARG2(*answer, (ipcarg_t) packet->length); 378 return EOK; 379 380 case NET_PACKET_GET: 381 packet = pm_find(IPC_GET_ID(call)); 382 if (!packet_is_valid(packet)) 383 return ENOENT; 384 return packet_reply(packet); 385 386 case NET_PACKET_GET_SIZE: 387 packet = pm_find(IPC_GET_ID(call)); 388 if (!packet_is_valid(packet)) 389 return ENOENT; 390 IPC_SET_ARG1(*answer, (ipcarg_t) packet->length); 391 *answer_count = 1; 392 return EOK; 393 394 case NET_PACKET_RELEASE: 395 return packet_release_wrapper(IPC_GET_ID(call)); 283 396 } 284 if(async_share_in_receive(&callid, &size) <= 0) return EINVAL; 285 if(size != packet->length){ 286 return ENOMEM; 287 } 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){ 292 packet_t packet; 293 294 *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 } 397 333 398 return ENOTSUP; 334 399 } -
uspace/lib/packet/include/packet_local.h
r95e3fd0b r515a00da 27 27 */ 28 28 29 /** @addtogroup packet30 * 29 /** @addtogroup libpacket 30 * @{ 31 31 */ 32 32 … … 34 34 */ 35 35 36 #ifndef __NET_PACKET_LOCAL_H__37 #define __NET_PACKET_LOCAL_H__36 #ifndef LIBPACKET_PACKET_LOCAL_H_ 37 #define LIBPACKET_PACKET_LOCAL_H_ 38 38 39 39 #include <net/packet.h> -
uspace/lib/packet/include/packet_server.h
r95e3fd0b r515a00da 27 27 */ 28 28 29 /** @addtogroup packet30 * 29 /** @addtogroup libpacket 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * Packet server. 35 * The hosting module has to be compiled with both the packet.c and the packet_server.c source files. 36 * To function correctly, initialization of the packet map by the pm_init() function has to happen at the first place. 37 * Then the packet messages have to be processed by the packet_server_message() function. 38 * The packet map should be released by the pm_destroy() function during the module termination. 39 * @see IS_NET_PACKET_MESSAGE() 34 * Packet server. 35 * The hosting module has to be compiled with both the packet.c and the 36 * packet_server.c source files. To function correctly, initialization of the 37 * packet map by the pm_init() function has to happen at the first place. Then 38 * the packet messages have to be processed by the packet_server_message() 39 * function. The packet map should be released by the pm_destroy() function 40 * during the module termination. 41 * @see IS_NET_PACKET_MESSAGE() 40 42 */ 41 43 42 #ifndef __NET_PACKET_SERVER_H__43 #define __NET_PACKET_SERVER_H__44 #ifndef LIBPACKET_PACKET_SERVER_H_ 45 #define LIBPACKET_PACKET_SERVER_H_ 44 46 45 47 #include <ipc/ipc.h> 46 48 47 /** Processes the packet server message. 48 * @param[in] callid The message identifier. 49 * @param[in] call The message parameters. 50 * @param[out] answer The message answer parameters. 51 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 52 * @returns EOK on success. 53 * @returns ENOMEM if there is not enough memory left. 54 * @returns ENOENT if there is no such packet as in the packet message parameter.. 55 * @returns ENOTSUP if the message is not known. 56 * @returns Other error codes as defined for the packet_release_wrapper() function. 57 */ 58 extern int packet_server_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count); 49 extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, 50 int *); 59 51 60 52 #endif
Note:
See TracChangeset
for help on using the changeset viewer.