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