Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ALSA: seq: prioq: Unify cell removal functions

Both snd_seq_prioq_remove_events() and snd_seq_prioq_leave() have a
very similar loop for removing events. Unify them with a callback for
code simplification.

Only the code refactoring, and no functional changes.

Link: https://lore.kernel.org/r/20240222132152.29063-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+84 -113
+84 -113
sound/core/seq/seq_prioq.c
··· 249 249 return f->cells; 250 250 } 251 251 252 - static inline int prioq_match(struct snd_seq_event_cell *cell, 253 - int client, int timestamp) 254 - { 255 - if (cell->event.source.client == client || 256 - cell->event.dest.client == client) 257 - return 1; 258 - if (!timestamp) 259 - return 0; 260 - switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { 261 - case SNDRV_SEQ_TIME_STAMP_TICK: 262 - if (cell->event.time.tick) 263 - return 1; 264 - break; 265 - case SNDRV_SEQ_TIME_STAMP_REAL: 266 - if (cell->event.time.time.tv_sec || 267 - cell->event.time.time.tv_nsec) 268 - return 1; 269 - break; 270 - } 271 - return 0; 272 - } 273 - 274 - /* remove cells for left client */ 275 - void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp) 252 + /* remove cells matching with the condition */ 253 + static void prioq_remove_cells(struct snd_seq_prioq *f, 254 + bool (*match)(struct snd_seq_event_cell *cell, 255 + void *arg), 256 + void *arg) 276 257 { 277 258 register struct snd_seq_event_cell *cell, *next; 278 259 unsigned long flags; ··· 262 281 263 282 /* collect all removed cells */ 264 283 spin_lock_irqsave(&f->lock, flags); 265 - cell = f->head; 266 - while (cell) { 284 + for (cell = f->head; cell; cell = next) { 267 285 next = cell->next; 268 - if (prioq_match(cell, client, timestamp)) { 269 - /* remove cell from prioq */ 270 - if (cell == f->head) { 271 - f->head = cell->next; 272 - } else { 273 - prev->next = cell->next; 274 - } 275 - if (cell == f->tail) 276 - f->tail = cell->next; 277 - f->cells--; 278 - /* add cell to free list */ 279 - cell->next = NULL; 280 - if (freefirst == NULL) { 281 - freefirst = cell; 282 - } else { 283 - freeprev->next = cell; 284 - } 285 - freeprev = cell; 286 - } else { 287 - #if 0 288 - pr_debug("ALSA: seq: type = %i, source = %i, dest = %i, " 289 - "client = %i\n", 290 - cell->event.type, 291 - cell->event.source.client, 292 - cell->event.dest.client, 293 - client); 294 - #endif 286 + if (!match(cell, arg)) { 295 287 prev = cell; 288 + continue; 296 289 } 297 - cell = next; 290 + 291 + /* remove cell from prioq */ 292 + if (cell == f->head) 293 + f->head = cell->next; 294 + else 295 + prev->next = cell->next; 296 + if (cell == f->tail) 297 + f->tail = cell->next; 298 + f->cells--; 299 + 300 + /* add cell to free list */ 301 + cell->next = NULL; 302 + if (freefirst == NULL) 303 + freefirst = cell; 304 + else 305 + freeprev->next = cell; 306 + freeprev = cell; 298 307 } 299 308 spin_unlock_irqrestore(&f->lock, flags); 300 309 ··· 296 325 } 297 326 } 298 327 299 - static int prioq_remove_match(struct snd_seq_remove_events *info, 300 - struct snd_seq_event *ev) 328 + struct prioq_match_arg { 329 + int client; 330 + int timestamp; 331 + }; 332 + 333 + static inline bool prioq_match(struct snd_seq_event_cell *cell, void *arg) 301 334 { 335 + struct prioq_match_arg *v = arg; 336 + 337 + if (cell->event.source.client == v->client || 338 + cell->event.dest.client == v->client) 339 + return true; 340 + if (!v->timestamp) 341 + return false; 342 + switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { 343 + case SNDRV_SEQ_TIME_STAMP_TICK: 344 + if (cell->event.time.tick) 345 + return true; 346 + break; 347 + case SNDRV_SEQ_TIME_STAMP_REAL: 348 + if (cell->event.time.time.tv_sec || 349 + cell->event.time.time.tv_nsec) 350 + return true; 351 + break; 352 + } 353 + return false; 354 + } 355 + 356 + /* remove cells for left client */ 357 + void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp) 358 + { 359 + struct prioq_match_arg arg = { client, timestamp }; 360 + 361 + return prioq_remove_cells(f, prioq_match, &arg); 362 + } 363 + 364 + struct prioq_remove_match_arg { 365 + int client; 366 + struct snd_seq_remove_events *info; 367 + }; 368 + 369 + static bool prioq_remove_match(struct snd_seq_event_cell *cell, void *arg) 370 + { 371 + struct prioq_remove_match_arg *v = arg; 372 + struct snd_seq_event *ev = &cell->event; 373 + struct snd_seq_remove_events *info = v->info; 302 374 int res; 375 + 376 + if (ev->source.client != v->client) 377 + return false; 303 378 304 379 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) { 305 380 if (ev->dest.client != info->dest.client || 306 381 ev->dest.port != info->dest.port) 307 - return 0; 382 + return false; 308 383 } 309 384 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) { 310 385 if (! snd_seq_ev_is_channel_type(ev)) 311 - return 0; 386 + return false; 312 387 /* data.note.channel and data.control.channel are identical */ 313 388 if (ev->data.note.channel != info->channel) 314 - return 0; 389 + return false; 315 390 } 316 391 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) { 317 392 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) ··· 365 348 else 366 349 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); 367 350 if (!res) 368 - return 0; 351 + return false; 369 352 } 370 353 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) { 371 354 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) ··· 373 356 else 374 357 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); 375 358 if (res) 376 - return 0; 359 + return false; 377 360 } 378 361 if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) { 379 362 if (ev->type != info->type) 380 - return 0; 363 + return false; 381 364 } 382 365 if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) { 383 366 /* Do not remove off events */ 384 367 switch (ev->type) { 385 368 case SNDRV_SEQ_EVENT_NOTEOFF: 386 369 /* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */ 387 - return 0; 370 + return false; 388 371 default: 389 372 break; 390 373 } 391 374 } 392 375 if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) { 393 376 if (info->tag != ev->tag) 394 - return 0; 377 + return false; 395 378 } 396 379 397 - return 1; 380 + return true; 398 381 } 399 382 400 383 /* remove cells matching remove criteria */ 401 384 void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client, 402 385 struct snd_seq_remove_events *info) 403 386 { 404 - struct snd_seq_event_cell *cell, *next; 405 - unsigned long flags; 406 - struct snd_seq_event_cell *prev = NULL; 407 - struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext; 387 + struct prioq_remove_match_arg arg = { client, info }; 408 388 409 - /* collect all removed cells */ 410 - spin_lock_irqsave(&f->lock, flags); 411 - cell = f->head; 412 - 413 - while (cell) { 414 - next = cell->next; 415 - if (cell->event.source.client == client && 416 - prioq_remove_match(info, &cell->event)) { 417 - 418 - /* remove cell from prioq */ 419 - if (cell == f->head) { 420 - f->head = cell->next; 421 - } else { 422 - prev->next = cell->next; 423 - } 424 - 425 - if (cell == f->tail) 426 - f->tail = cell->next; 427 - f->cells--; 428 - 429 - /* add cell to free list */ 430 - cell->next = NULL; 431 - if (freefirst == NULL) { 432 - freefirst = cell; 433 - } else { 434 - freeprev->next = cell; 435 - } 436 - 437 - freeprev = cell; 438 - } else { 439 - prev = cell; 440 - } 441 - cell = next; 442 - } 443 - spin_unlock_irqrestore(&f->lock, flags); 444 - 445 - /* remove selected cells */ 446 - while (freefirst) { 447 - freenext = freefirst->next; 448 - snd_seq_cell_free(freefirst); 449 - freefirst = freenext; 450 - } 389 + return prioq_remove_cells(f, prioq_remove_match, &arg); 451 390 } 452 - 453 -