| 444 | | #if defined(linux) |
|---|
| 445 | | static JSList * |
|---|
| 446 | | jack_process_external(jack_engine_t *engine, JSList *node) |
|---|
| 447 | | { |
|---|
| 448 | | int status; |
|---|
| 449 | | char c; |
|---|
| 450 | | float delayed_usecs; |
|---|
| 451 | | jack_client_internal_t *client; |
|---|
| 452 | | jack_client_control_t *ctl; |
|---|
| 453 | | jack_time_t now, then; |
|---|
| 454 | | |
|---|
| 455 | | client = (jack_client_internal_t *) node->data; |
|---|
| 456 | | |
|---|
| 457 | | ctl = client->control; |
|---|
| 458 | | |
|---|
| 459 | | /* external subgraph */ |
|---|
| 460 | | |
|---|
| 461 | | ctl->state = Triggered; // a race exists if we do this after the write(2) |
|---|
| 462 | | ctl->signalled_at = jack_get_microseconds(); |
|---|
| 463 | | ctl->awake_at = 0; |
|---|
| 464 | | ctl->finished_at = 0; |
|---|
| 465 | | |
|---|
| 466 | | engine->current_client = client; |
|---|
| 467 | | |
|---|
| 468 | | DEBUG ("calling process() on an external subgraph, fd==%d", client->subgraph_start_fd); |
|---|
| 469 | | |
|---|
| 470 | | if (write (client->subgraph_start_fd, &c, sizeof (c)) != sizeof (c)) { |
|---|
| 471 | | jack_error ("cannot initiate graph processing (%s)", strerror (errno)); |
|---|
| 472 | | engine->process_errors++; |
|---|
| 473 | | return NULL; /* will stop the loop */ |
|---|
| 474 | | } |
|---|
| 475 | | |
|---|
| 476 | | then = jack_get_microseconds (); |
|---|
| 477 | | |
|---|
| 478 | | if (engine->asio_mode) { |
|---|
| 479 | | engine->driver->wait (engine->driver, client->subgraph_wait_fd, &status, &delayed_usecs); |
|---|
| 480 | | } else { |
|---|
| 481 | | struct pollfd pfd[1]; |
|---|
| 482 | | int poll_timeout = (engine->control->real_time == 0 ? engine->client_timeout_msecs : engine->driver->period_usecs/1000); |
|---|
| 483 | | |
|---|
| 484 | | pfd[0].fd = client->subgraph_wait_fd; |
|---|
| 485 | | pfd[0].events = POLLERR|POLLIN|POLLHUP|POLLNVAL; |
|---|
| 486 | | |
|---|
| 487 | | DEBUG ("waiting on fd==%d for process() subgraph to finish", client->subgraph_wait_fd); |
|---|
| 488 | | |
|---|
| 489 | | if (poll (pfd, 1, poll_timeout) < 0) { |
|---|
| 490 | | jack_error ("poll on subgraph processing failed (%s)", strerror (errno)); |
|---|
| 491 | | status = -1; |
|---|
| 492 | | } |
|---|
| 493 | | |
|---|
| 494 | | if (pfd[0].revents & ~POLLIN) { |
|---|
| 495 | | jack_error ("subgraph starting at %s lost client", client->control->name); |
|---|
| 496 | | status = -2; |
|---|
| 497 | | } |
|---|
| 498 | | |
|---|
| 499 | | if (pfd[0].revents & POLLIN) { |
|---|
| 500 | | status = 0; |
|---|
| 501 | | } else { |
|---|
| 502 | | jack_error ("subgraph starting at %s timed out (subgraph_wait_fd=%d, status = %d, state = %s)", |
|---|
| 503 | | client->control->name, client->subgraph_wait_fd, status, |
|---|
| 504 | | client_state_names[client->control->state]); |
|---|
| 505 | | status = 1; |
|---|
| 506 | | } |
|---|
| 507 | | } |
|---|
| 508 | | |
|---|
| 509 | | now = jack_get_microseconds (); |
|---|
| 510 | | |
|---|
| 511 | | if (status != 0) { |
|---|
| 512 | | if (engine->verbose) { |
|---|
| 513 | | fprintf (stderr, "at %Lu client waiting on %d took %Lu usecs, status = %d sig = %Lu " |
|---|
| 514 | | "awa = %Lu fin = %Lu dur=%Lu\n", |
|---|
| 515 | | now, |
|---|
| 516 | | client->subgraph_wait_fd, |
|---|
| 517 | | now - then, |
|---|
| 518 | | status, |
|---|
| 519 | | ctl->signalled_at, |
|---|
| 520 | | ctl->awake_at, |
|---|
| 521 | | ctl->finished_at, |
|---|
| 522 | | ctl->finished_at ? ctl->finished_at - ctl->signalled_at : 0); |
|---|
| 523 | | } |
|---|
| 524 | | |
|---|
| 525 | | /* we can only consider the timeout a client error if it actually woke up. |
|---|
| 526 | | its possible that the kernel scheduler screwed us up and |
|---|
| 527 | | never woke up the client in time. sigh. |
|---|
| 528 | | */ |
|---|
| 529 | | |
|---|
| 530 | | if (ctl->awake_at > 0) { |
|---|
| 531 | | ctl->timed_out++; |
|---|
| 532 | | } |
|---|
| 533 | | |
|---|
| 534 | | engine->process_errors++; |
|---|
| 535 | | return NULL; /* will stop the loop */ |
|---|
| 536 | | } else { |
|---|
| 537 | | DEBUG ("reading byte from subgraph_wait_fd==%d", client->subgraph_wait_fd); |
|---|
| 538 | | |
|---|
| 539 | | if (read (client->subgraph_wait_fd, &c, sizeof(c)) != sizeof (c)) { |
|---|
| 540 | | jack_error ("pp: cannot clean up byte from graph wait fd (%s)", strerror (errno)); |
|---|
| 541 | | client->error++; |
|---|
| 542 | | return NULL; /* will stop the loop */ |
|---|
| 543 | | } |
|---|
| 544 | | } |
|---|
| 545 | | |
|---|
| 546 | | /* Move to next internal client (or end of client list) */ |
|---|
| 547 | | |
|---|
| 548 | | while (node) { |
|---|
| 549 | | if (jack_client_is_internal (((jack_client_internal_t *) node->data))) { |
|---|
| 550 | | break; |
|---|
| 551 | | } |
|---|
| 552 | | node = jack_slist_next (node); |
|---|
| 553 | | } |
|---|
| 554 | | |
|---|
| 555 | | return node; |
|---|
| 556 | | } |
|---|
| 557 | | |
|---|
| 558 | | #elif defined(__APPLE__) && defined(__POWERPC__) |
|---|
| 559 | | |
|---|
| | 444 | #if defined(__APPLE__) && defined(__POWERPC__) |
|---|
| | 465 | #else |
|---|
| | 466 | static JSList * |
|---|
| | 467 | jack_process_external(jack_engine_t *engine, JSList *node) |
|---|
| | 468 | { |
|---|
| | 469 | int status; |
|---|
| | 470 | char c; |
|---|
| | 471 | float delayed_usecs; |
|---|
| | 472 | jack_client_internal_t *client; |
|---|
| | 473 | jack_client_control_t *ctl; |
|---|
| | 474 | jack_time_t now, then; |
|---|
| | 475 | |
|---|
| | 476 | client = (jack_client_internal_t *) node->data; |
|---|
| | 477 | |
|---|
| | 478 | ctl = client->control; |
|---|
| | 479 | |
|---|
| | 480 | /* external subgraph */ |
|---|
| | 481 | |
|---|
| | 482 | ctl->state = Triggered; // a race exists if we do this after the write(2) |
|---|
| | 483 | ctl->signalled_at = jack_get_microseconds(); |
|---|
| | 484 | ctl->awake_at = 0; |
|---|
| | 485 | ctl->finished_at = 0; |
|---|
| | 486 | |
|---|
| | 487 | engine->current_client = client; |
|---|
| | 488 | |
|---|
| | 489 | DEBUG ("calling process() on an external subgraph, fd==%d", client->subgraph_start_fd); |
|---|
| | 490 | |
|---|
| | 491 | if (write (client->subgraph_start_fd, &c, sizeof (c)) != sizeof (c)) { |
|---|
| | 492 | jack_error ("cannot initiate graph processing (%s)", strerror (errno)); |
|---|
| | 493 | engine->process_errors++; |
|---|
| | 494 | return NULL; /* will stop the loop */ |
|---|
| | 495 | } |
|---|
| | 496 | |
|---|
| | 497 | then = jack_get_microseconds (); |
|---|
| | 498 | |
|---|
| | 499 | if (engine->asio_mode) { |
|---|
| | 500 | engine->driver->wait (engine->driver, client->subgraph_wait_fd, &status, &delayed_usecs); |
|---|
| | 501 | } else { |
|---|
| | 502 | struct pollfd pfd[1]; |
|---|
| | 503 | int poll_timeout = (engine->control->real_time == 0 ? engine->client_timeout_msecs : engine->driver->period_usecs/1000); |
|---|
| | 504 | |
|---|
| | 505 | pfd[0].fd = client->subgraph_wait_fd; |
|---|
| | 506 | pfd[0].events = POLLERR|POLLIN|POLLHUP|POLLNVAL; |
|---|
| | 507 | |
|---|
| | 508 | DEBUG ("waiting on fd==%d for process() subgraph to finish", client->subgraph_wait_fd); |
|---|
| | 509 | |
|---|
| | 510 | if (poll (pfd, 1, poll_timeout) < 0) { |
|---|
| | 511 | jack_error ("poll on subgraph processing failed (%s)", strerror (errno)); |
|---|
| | 512 | status = -1; |
|---|
| | 513 | } |
|---|
| | 514 | |
|---|
| | 515 | if (pfd[0].revents & ~POLLIN) { |
|---|
| | 516 | jack_error ("subgraph starting at %s lost client", client->control->name); |
|---|
| | 517 | status = -2; |
|---|
| | 518 | } |
|---|
| | 519 | |
|---|
| | 520 | if (pfd[0].revents & POLLIN) { |
|---|
| | 521 | status = 0; |
|---|
| | 522 | } else { |
|---|
| | 523 | jack_error ("subgraph starting at %s timed out (subgraph_wait_fd=%d, status = %d, state = %s)", |
|---|
| | 524 | client->control->name, client->subgraph_wait_fd, status, |
|---|
| | 525 | client_state_names[client->control->state]); |
|---|
| | 526 | status = 1; |
|---|
| | 527 | } |
|---|
| | 528 | } |
|---|
| | 529 | |
|---|
| | 530 | now = jack_get_microseconds (); |
|---|
| | 531 | |
|---|
| | 532 | if (status != 0) { |
|---|
| | 533 | if (engine->verbose) { |
|---|
| | 534 | fprintf (stderr, "at %Lu client waiting on %d took %Lu usecs, status = %d sig = %Lu " |
|---|
| | 535 | "awa = %Lu fin = %Lu dur=%Lu\n", |
|---|
| | 536 | now, |
|---|
| | 537 | client->subgraph_wait_fd, |
|---|
| | 538 | now - then, |
|---|
| | 539 | status, |
|---|
| | 540 | ctl->signalled_at, |
|---|
| | 541 | ctl->awake_at, |
|---|
| | 542 | ctl->finished_at, |
|---|
| | 543 | ctl->finished_at ? ctl->finished_at - ctl->signalled_at : 0); |
|---|
| | 544 | } |
|---|
| | 545 | |
|---|
| | 546 | /* we can only consider the timeout a client error if it actually woke up. |
|---|
| | 547 | its possible that the kernel scheduler screwed us up and |
|---|
| | 548 | never woke up the client in time. sigh. |
|---|
| | 549 | */ |
|---|
| | 550 | |
|---|
| | 551 | if (ctl->awake_at > 0) { |
|---|
| | 552 | ctl->timed_out++; |
|---|
| | 553 | } |
|---|
| | 554 | |
|---|
| | 555 | engine->process_errors++; |
|---|
| | 556 | return NULL; /* will stop the loop */ |
|---|
| | 557 | } else { |
|---|
| | 558 | DEBUG ("reading byte from subgraph_wait_fd==%d", client->subgraph_wait_fd); |
|---|
| | 559 | |
|---|
| | 560 | if (read (client->subgraph_wait_fd, &c, sizeof(c)) != sizeof (c)) { |
|---|
| | 561 | jack_error ("pp: cannot clean up byte from graph wait fd (%s)", strerror (errno)); |
|---|
| | 562 | client->error++; |
|---|
| | 563 | return NULL; /* will stop the loop */ |
|---|
| | 564 | } |
|---|
| | 565 | } |
|---|
| | 566 | |
|---|
| | 567 | /* Move to next internal client (or end of client list) */ |
|---|
| | 568 | |
|---|
| | 569 | while (node) { |
|---|
| | 570 | if (jack_client_is_internal (((jack_client_internal_t *) node->data))) { |
|---|
| | 571 | break; |
|---|
| | 572 | } |
|---|
| | 573 | node = jack_slist_next (node); |
|---|
| | 574 | } |
|---|
| | 575 | |
|---|
| | 576 | return node; |
|---|
| | 577 | } |
|---|
| | 578 | |
|---|