Changes in uspace/lib/packet/generic/packet_server.c [f63a591d:dd5046dd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/packet/generic/packet_server.c
rf63a591d rdd5046dd 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> 36 38 37 39 #include <align.h> … … 39 41 #include <async.h> 40 42 #include <errno.h> 41 #include <err.h>42 43 #include <fibril_synch.h> 43 44 #include <unistd.h> … … 51 52 #include <net/packet_header.h> 52 53 53 #include <packet_server.h>54 #include <packet_local.h>55 56 54 #define FREE_QUEUES_COUNT 7 57 55 58 /** The default address length reserved for new packets. 59 */ 56 /** The default address length reserved for new packets. */ 60 57 #define DEFAULT_ADDR_LEN 32 61 58 62 /** The default prefix reserved for new packets. 63 */ 59 /** The default prefix reserved for new packets. */ 64 60 #define DEFAULT_PREFIX 64 65 61 66 /** The default suffix reserved for new packets. 67 */ 62 /** The default suffix reserved for new packets. */ 68 63 #define DEFAULT_SUFFIX 64 69 64 70 /** Packet server global data. 71 */ 72 static struct{ 73 /** Safety lock. 74 */ 65 /** Packet server global data. */ 66 static struct { 67 /** Safety lock. */ 75 68 fibril_mutex_t lock; 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. 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. 82 76 */ 83 77 size_t sizes[FREE_QUEUES_COUNT]; 84 /** Total packets allocated.85 */78 79 /** Total packets allocated. */ 86 80 unsigned int count; 87 81 } ps_globals = { 88 82 .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}, 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 }, 91 101 .count = 0 92 102 }; 93 103 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 103 104 /** 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){ 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 { 111 117 // clear the packet content 112 bzero(((void *) packet) + sizeof(struct packet), packet->length - sizeof(struct packet)); 118 bzero(((void *) packet) + sizeof(packet_t), 119 packet->length - sizeof(packet_t)); 120 113 121 // clear the packet header 114 122 packet->order = 0; … … 117 125 packet->next = 0; 118 126 packet->addr_len = 0; 119 packet->src_addr = sizeof( struct packet);127 packet->src_addr = sizeof(packet_t); 120 128 packet->dest_addr = packet->src_addr + addr_len; 121 129 packet->max_prefix = max_prefix; … … 125 133 } 126 134 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; 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; 141 155 142 156 // already locked 143 packet = (packet_t) mmap(NULL, length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); 144 if(packet == MAP_FAILED){ 157 packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE, 158 MAP_SHARED | MAP_ANONYMOUS, 0, 0); 159 if (packet == MAP_FAILED) 145 160 return NULL; 146 } 147 ++ ps_globals.count;161 162 ps_globals.count++; 148 163 packet->packet_id = ps_globals.count; 149 164 packet->length = length; 150 165 packet_init(packet, addr_len, max_prefix, max_content, max_suffix); 151 166 packet->magic_value = PACKET_MAGIC_VALUE; 152 if(ERROR_OCCURRED(pm_add(packet))){ 167 rc = pm_add(packet); 168 if (rc != EOK) { 153 169 munmap(packet, packet->length); 154 170 return NULL; 155 171 } 172 156 173 return packet; 157 174 } … … 163 180 * Lock the global data during its processing. 164 181 * 165 * @param[in] addr_len The source and destination addresses166 * maximal length inbytes.167 * @param[in] max_prefix 182 * @param[in] addr_len The source and destination addresses maximal length in 183 * bytes. 184 * @param[in] max_prefix The maximal prefix length in bytes. 168 185 * @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); 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); 180 196 181 197 fibril_mutex_lock(&ps_globals.lock); 182 198 183 packet_t packet;199 packet_t *packet; 184 200 unsigned int index; 185 201 186 for (index = 0; index < FREE_QUEUES_COUNT - 1; index++) { 187 if (length <= ps_globals.sizes[index]) { 188 packet = ps_globals.free[index]; 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); 189 216 190 while (packet_is_valid(packet) && (packet->length < length)) 191 packet = pm_find(packet->next); 217 packet_init(packet, addr_len, max_prefix, max_content, 218 max_suffix); 219 fibril_mutex_unlock(&ps_globals.lock); 192 220 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 } 221 return packet; 205 222 } 206 223 } … … 214 231 } 215 232 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 228 233 /** Release the packet and returns it to the appropriate free packet queue. 229 234 * 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){ 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 { 236 242 int index; 237 243 int result; 238 244 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); 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); 243 252 assert(result == EOK); 244 253 } 245 254 246 255 /** 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){ 252 packet_t packet; 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; 253 264 254 265 packet = pm_find(packet_id); 255 if (! packet_is_valid(packet)){266 if (!packet_is_valid(packet)) 256 267 return ENOENT; 257 } 268 258 269 fibril_mutex_lock(&ps_globals.lock); 259 270 pq_destroy(packet, packet_release); 260 271 fibril_mutex_unlock(&ps_globals.lock); 272 261 273 return EOK; 262 274 } 263 275 264 void pq_release_local(int phone, packet_id_t packet_id)265 {266 (void) packet_release_wrapper(packet_id);267 }268 269 276 /** 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){ 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 { 278 287 ipc_callid_t callid; 279 288 size_t size; 280 289 281 if (! packet_is_valid(packet)){290 if (!packet_is_valid(packet)) 282 291 return EINVAL; 283 } 284 if(async_share_in_receive(&callid, &size) <= 0) return EINVAL; 285 if(size != packet->length){ 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); 286 300 return ENOMEM; 287 301 } 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; 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; 293 327 294 328 *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 } 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 333 375 return ENOTSUP; 334 376 }
Note:
See TracChangeset
for help on using the changeset viewer.