diff options
| author | 2014-01-09 11:31:08 +0100 | |
|---|---|---|
| committer | 2014-01-09 11:31:08 +0100 | |
| commit | d04ce1b524f68dda6b75cfff69f70f4b4ad8e1d5 (patch) | |
| tree | 3a906994c7a8e7c8120d982f00f4c6f636364a8b /src | |
| parent | bad870a5d072e5959f1adb01648dc3dbcc790b3b (diff) | |
| download | usbmuxd-d04ce1b524f68dda6b75cfff69f70f4b4ad8e1d5.tar.gz usbmuxd-d04ce1b524f68dda6b75cfff69f70f4b4ad8e1d5.tar.bz2 | |
device: make device_list access thread safe
Diffstat (limited to 'src')
| -rw-r--r-- | src/device.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/device.c b/src/device.c index 1e3cc83..29be9d1 100644 --- a/src/device.c +++ b/src/device.c | |||
| @@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <stdint.h> | 32 | #include <stdint.h> |
| 33 | #include <inttypes.h> | 33 | #include <inttypes.h> |
| 34 | #include <pthread.h> | ||
| 34 | #include "device.h" | 35 | #include "device.h" |
| 35 | #include "client.h" | 36 | #include "client.h" |
| 36 | #include "preflight.h" | 37 | #include "preflight.h" |
| @@ -116,6 +117,7 @@ struct mux_device | |||
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| 118 | static struct collection device_list; | 119 | static struct collection device_list; |
| 120 | pthread_mutex_t device_list_mutex; | ||
| 119 | 121 | ||
| 120 | static uint64_t mstime64(void) | 122 | static uint64_t mstime64(void) |
| 121 | { | 123 | { |
| @@ -128,6 +130,7 @@ static int get_next_device_id(void) | |||
| 128 | { | 130 | { |
| 129 | while(1) { | 131 | while(1) { |
| 130 | int ok = 1; | 132 | int ok = 1; |
| 133 | pthread_mutex_lock(&device_list_mutex); | ||
| 131 | FOREACH(struct mux_device *dev, &device_list) { | 134 | FOREACH(struct mux_device *dev, &device_list) { |
| 132 | if(dev->id == next_device_id) { | 135 | if(dev->id == next_device_id) { |
| 133 | next_device_id++; | 136 | next_device_id++; |
| @@ -135,6 +138,7 @@ static int get_next_device_id(void) | |||
| 135 | break; | 138 | break; |
| 136 | } | 139 | } |
| 137 | } ENDFOREACH | 140 | } ENDFOREACH |
| 141 | pthread_mutex_unlock(&device_list_mutex); | ||
| 138 | if(ok) | 142 | if(ok) |
| 139 | return next_device_id++; | 143 | return next_device_id++; |
| 140 | } | 144 | } |
| @@ -271,12 +275,14 @@ static void connection_teardown(struct mux_connection *conn) | |||
| 271 | int device_start_connect(int device_id, uint16_t dport, struct mux_client *client) | 275 | int device_start_connect(int device_id, uint16_t dport, struct mux_client *client) |
| 272 | { | 276 | { |
| 273 | struct mux_device *dev = NULL; | 277 | struct mux_device *dev = NULL; |
| 278 | pthread_mutex_lock(&device_list_mutex); | ||
| 274 | FOREACH(struct mux_device *cdev, &device_list) { | 279 | FOREACH(struct mux_device *cdev, &device_list) { |
| 275 | if(cdev->id == device_id) { | 280 | if(cdev->id == device_id) { |
| 276 | dev = cdev; | 281 | dev = cdev; |
| 277 | break; | 282 | break; |
| 278 | } | 283 | } |
| 279 | } ENDFOREACH | 284 | } ENDFOREACH |
| 285 | pthread_mutex_unlock(&device_list_mutex); | ||
| 280 | if(!dev) { | 286 | if(!dev) { |
| 281 | usbmuxd_log(LL_WARNING, "Attempted to connect to nonexistent device %d", device_id); | 287 | usbmuxd_log(LL_WARNING, "Attempted to connect to nonexistent device %d", device_id); |
| 282 | return -RESULT_BADDEV; | 288 | return -RESULT_BADDEV; |
| @@ -359,6 +365,7 @@ static void update_connection(struct mux_connection *conn) | |||
| 359 | void device_client_process(int device_id, struct mux_client *client, short events) | 365 | void device_client_process(int device_id, struct mux_client *client, short events) |
| 360 | { | 366 | { |
| 361 | struct mux_connection *conn = NULL; | 367 | struct mux_connection *conn = NULL; |
| 368 | pthread_mutex_lock(&device_list_mutex); | ||
| 362 | FOREACH(struct mux_device *dev, &device_list) { | 369 | FOREACH(struct mux_device *dev, &device_list) { |
| 363 | if(dev->id == device_id) { | 370 | if(dev->id == device_id) { |
| 364 | FOREACH(struct mux_connection *lconn, &dev->connections) { | 371 | FOREACH(struct mux_connection *lconn, &dev->connections) { |
| @@ -370,6 +377,7 @@ void device_client_process(int device_id, struct mux_client *client, short event | |||
| 370 | break; | 377 | break; |
| 371 | } | 378 | } |
| 372 | } ENDFOREACH | 379 | } ENDFOREACH |
| 380 | pthread_mutex_unlock(&device_list_mutex); | ||
| 373 | 381 | ||
| 374 | if(!conn) { | 382 | if(!conn) { |
| 375 | usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); | 383 | usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); |
| @@ -427,18 +435,22 @@ static void connection_device_input(struct mux_connection *conn, unsigned char * | |||
| 427 | 435 | ||
| 428 | void device_abort_connect(int device_id, struct mux_client *client) | 436 | void device_abort_connect(int device_id, struct mux_client *client) |
| 429 | { | 437 | { |
| 438 | pthread_mutex_lock(&device_list_mutex); | ||
| 430 | FOREACH(struct mux_device *dev, &device_list) { | 439 | FOREACH(struct mux_device *dev, &device_list) { |
| 431 | if(dev->id == device_id) { | 440 | if(dev->id == device_id) { |
| 432 | FOREACH(struct mux_connection *conn, &dev->connections) { | 441 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| 433 | if(conn->client == client) { | 442 | if(conn->client == client) { |
| 434 | connection_teardown(conn); | 443 | connection_teardown(conn); |
| 444 | pthread_mutex_unlock(&device_list_mutex); | ||
| 435 | return; | 445 | return; |
| 436 | } | 446 | } |
| 437 | } ENDFOREACH | 447 | } ENDFOREACH |
| 448 | pthread_mutex_unlock(&device_list_mutex); | ||
| 438 | usbmuxd_log(LL_WARNING, "Attempted to abort for nonexistent connection for device %d", device_id); | 449 | usbmuxd_log(LL_WARNING, "Attempted to abort for nonexistent connection for device %d", device_id); |
| 439 | return; | 450 | return; |
| 440 | } | 451 | } |
| 441 | } ENDFOREACH | 452 | } ENDFOREACH |
| 453 | pthread_mutex_unlock(&device_list_mutex); | ||
| 442 | usbmuxd_log(LL_WARNING, "Attempted to abort connection for nonexistent device %d", device_id); | 454 | usbmuxd_log(LL_WARNING, "Attempted to abort connection for nonexistent device %d", device_id); |
| 443 | } | 455 | } |
| 444 | 456 | ||
| @@ -452,7 +464,9 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 452 | vh->minor = ntohl(vh->minor); | 464 | vh->minor = ntohl(vh->minor); |
| 453 | if(vh->major != 1 || vh->minor != 0) { | 465 | if(vh->major != 1 || vh->minor != 0) { |
| 454 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d\n", dev->id, vh->major, vh->minor); | 466 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d\n", dev->id, vh->major, vh->minor); |
| 467 | pthread_mutex_lock(&device_list_mutex); | ||
| 455 | collection_remove(&device_list, dev); | 468 | collection_remove(&device_list, dev); |
| 469 | pthread_mutex_unlock(&device_list_mutex); | ||
| 456 | free(dev); | 470 | free(dev); |
| 457 | return; | 471 | return; |
| 458 | } | 472 | } |
| @@ -548,12 +562,14 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned | |||
| 548 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) | 562 | void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) |
| 549 | { | 563 | { |
| 550 | struct mux_device *dev = NULL; | 564 | struct mux_device *dev = NULL; |
| 565 | pthread_mutex_lock(&device_list_mutex); | ||
| 551 | FOREACH(struct mux_device *tdev, &device_list) { | 566 | FOREACH(struct mux_device *tdev, &device_list) { |
| 552 | if(tdev->usbdev == usbdev) { | 567 | if(tdev->usbdev == usbdev) { |
| 553 | dev = tdev; | 568 | dev = tdev; |
| 554 | break; | 569 | break; |
| 555 | } | 570 | } |
| 556 | } ENDFOREACH | 571 | } ENDFOREACH |
| 572 | pthread_mutex_unlock(&device_list_mutex); | ||
| 557 | if(!dev) { | 573 | if(!dev) { |
| 558 | usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); | 574 | usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); |
| 559 | return; | 575 | return; |
| @@ -659,12 +675,15 @@ int device_add(struct usb_device *usbdev) | |||
| 659 | free(dev); | 675 | free(dev); |
| 660 | return res; | 676 | return res; |
| 661 | } | 677 | } |
| 678 | pthread_mutex_lock(&device_list_mutex); | ||
| 662 | collection_add(&device_list, dev); | 679 | collection_add(&device_list, dev); |
| 680 | pthread_mutex_unlock(&device_list_mutex); | ||
| 663 | return 0; | 681 | return 0; |
| 664 | } | 682 | } |
| 665 | 683 | ||
| 666 | void device_remove(struct usb_device *usbdev) | 684 | void device_remove(struct usb_device *usbdev) |
| 667 | { | 685 | { |
| 686 | pthread_mutex_lock(&device_list_mutex); | ||
| 668 | FOREACH(struct mux_device *dev, &device_list) { | 687 | FOREACH(struct mux_device *dev, &device_list) { |
| 669 | if(dev->usbdev == usbdev) { | 688 | if(dev->usbdev == usbdev) { |
| 670 | usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev)); | 689 | usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev)); |
| @@ -680,47 +699,57 @@ void device_remove(struct usb_device *usbdev) | |||
| 680 | preflight_device_remove_cb(dev->preflight_cb_data); | 699 | preflight_device_remove_cb(dev->preflight_cb_data); |
| 681 | } | 700 | } |
| 682 | collection_remove(&device_list, dev); | 701 | collection_remove(&device_list, dev); |
| 702 | pthread_mutex_unlock(&device_list_mutex); | ||
| 683 | free(dev->pktbuf); | 703 | free(dev->pktbuf); |
| 684 | free(dev); | 704 | free(dev); |
| 685 | return; | 705 | return; |
| 686 | } | 706 | } |
| 687 | } ENDFOREACH | 707 | } ENDFOREACH |
| 708 | pthread_mutex_unlock(&device_list_mutex); | ||
| 709 | |||
| 688 | usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); | 710 | usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); |
| 689 | } | 711 | } |
| 690 | 712 | ||
| 691 | void device_set_visible(int device_id) | 713 | void device_set_visible(int device_id) |
| 692 | { | 714 | { |
| 715 | pthread_mutex_lock(&device_list_mutex); | ||
| 693 | FOREACH(struct mux_device *dev, &device_list) { | 716 | FOREACH(struct mux_device *dev, &device_list) { |
| 694 | if(dev->id == device_id) { | 717 | if(dev->id == device_id) { |
| 695 | dev->visible = 1; | 718 | dev->visible = 1; |
| 696 | break; | 719 | break; |
| 697 | } | 720 | } |
| 698 | } ENDFOREACH | 721 | } ENDFOREACH |
| 722 | pthread_mutex_unlock(&device_list_mutex); | ||
| 699 | } | 723 | } |
| 700 | 724 | ||
| 701 | void device_set_preflight_cb_data(int device_id, void* data) | 725 | void device_set_preflight_cb_data(int device_id, void* data) |
| 702 | { | 726 | { |
| 727 | pthread_mutex_lock(&device_list_mutex); | ||
| 703 | FOREACH(struct mux_device *dev, &device_list) { | 728 | FOREACH(struct mux_device *dev, &device_list) { |
| 704 | if(dev->id == device_id) { | 729 | if(dev->id == device_id) { |
| 705 | dev->preflight_cb_data = data; | 730 | dev->preflight_cb_data = data; |
| 706 | break; | 731 | break; |
| 707 | } | 732 | } |
| 708 | } ENDFOREACH | 733 | } ENDFOREACH |
| 734 | pthread_mutex_unlock(&device_list_mutex); | ||
| 709 | } | 735 | } |
| 710 | 736 | ||
| 711 | int device_get_count(int include_hidden) | 737 | int device_get_count(int include_hidden) |
| 712 | { | 738 | { |
| 713 | int count = 0; | 739 | int count = 0; |
| 740 | pthread_mutex_unlock(&device_list_mutex); | ||
| 714 | FOREACH(struct mux_device *dev, &device_list) { | 741 | FOREACH(struct mux_device *dev, &device_list) { |
| 715 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) | 742 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) |
| 716 | count++; | 743 | count++; |
| 717 | } ENDFOREACH | 744 | } ENDFOREACH |
| 745 | pthread_mutex_unlock(&device_list_mutex); | ||
| 718 | return count; | 746 | return count; |
| 719 | } | 747 | } |
| 720 | 748 | ||
| 721 | int device_get_list(int include_hidden, struct device_info *p) | 749 | int device_get_list(int include_hidden, struct device_info *p) |
| 722 | { | 750 | { |
| 723 | int count = 0; | 751 | int count = 0; |
| 752 | pthread_mutex_lock(&device_list_mutex); | ||
| 724 | FOREACH(struct mux_device *dev, &device_list) { | 753 | FOREACH(struct mux_device *dev, &device_list) { |
| 725 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) { | 754 | if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) { |
| 726 | p->id = dev->id; | 755 | p->id = dev->id; |
| @@ -731,12 +760,14 @@ int device_get_list(int include_hidden, struct device_info *p) | |||
| 731 | p++; | 760 | p++; |
| 732 | } | 761 | } |
| 733 | } ENDFOREACH | 762 | } ENDFOREACH |
| 763 | pthread_mutex_unlock(&device_list_mutex); | ||
| 734 | return count; | 764 | return count; |
| 735 | } | 765 | } |
| 736 | 766 | ||
| 737 | int device_get_timeout(void) | 767 | int device_get_timeout(void) |
| 738 | { | 768 | { |
| 739 | uint64_t oldest = (uint64_t)-1LL; | 769 | uint64_t oldest = (uint64_t)-1LL; |
| 770 | pthread_mutex_lock(&device_list_mutex); | ||
| 740 | FOREACH(struct mux_device *dev, &device_list) { | 771 | FOREACH(struct mux_device *dev, &device_list) { |
| 741 | if(dev->state == MUXDEV_ACTIVE) { | 772 | if(dev->state == MUXDEV_ACTIVE) { |
| 742 | FOREACH(struct mux_connection *conn, &dev->connections) { | 773 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| @@ -745,6 +776,7 @@ int device_get_timeout(void) | |||
| 745 | } ENDFOREACH | 776 | } ENDFOREACH |
| 746 | } | 777 | } |
| 747 | } ENDFOREACH | 778 | } ENDFOREACH |
| 779 | pthread_mutex_unlock(&device_list_mutex); | ||
| 748 | uint64_t ct = mstime64(); | 780 | uint64_t ct = mstime64(); |
| 749 | if((int64_t)oldest == -1LL) | 781 | if((int64_t)oldest == -1LL) |
| 750 | return 100000; //meh | 782 | return 100000; //meh |
| @@ -756,6 +788,7 @@ int device_get_timeout(void) | |||
| 756 | void device_check_timeouts(void) | 788 | void device_check_timeouts(void) |
| 757 | { | 789 | { |
| 758 | uint64_t ct = mstime64(); | 790 | uint64_t ct = mstime64(); |
| 791 | pthread_mutex_lock(&device_list_mutex); | ||
| 759 | FOREACH(struct mux_device *dev, &device_list) { | 792 | FOREACH(struct mux_device *dev, &device_list) { |
| 760 | if(dev->state == MUXDEV_ACTIVE) { | 793 | if(dev->state == MUXDEV_ACTIVE) { |
| 761 | FOREACH(struct mux_connection *conn, &dev->connections) { | 794 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| @@ -771,12 +804,14 @@ void device_check_timeouts(void) | |||
| 771 | } ENDFOREACH | 804 | } ENDFOREACH |
| 772 | } | 805 | } |
| 773 | } ENDFOREACH | 806 | } ENDFOREACH |
| 807 | pthread_mutex_unlock(&device_list_mutex); | ||
| 774 | } | 808 | } |
| 775 | 809 | ||
| 776 | void device_init(void) | 810 | void device_init(void) |
| 777 | { | 811 | { |
| 778 | usbmuxd_log(LL_DEBUG, "device_init"); | 812 | usbmuxd_log(LL_DEBUG, "device_init"); |
| 779 | collection_init(&device_list); | 813 | collection_init(&device_list); |
| 814 | pthread_mutex_init(&device_list_mutex, NULL); | ||
| 780 | next_device_id = 1; | 815 | next_device_id = 1; |
| 781 | } | 816 | } |
| 782 | 817 | ||
| @@ -797,6 +832,7 @@ void device_kill_connections(void) | |||
| 797 | void device_shutdown(void) | 832 | void device_shutdown(void) |
| 798 | { | 833 | { |
| 799 | usbmuxd_log(LL_DEBUG, "device_shutdown"); | 834 | usbmuxd_log(LL_DEBUG, "device_shutdown"); |
| 835 | pthread_mutex_lock(&device_list_mutex); | ||
| 800 | FOREACH(struct mux_device *dev, &device_list) { | 836 | FOREACH(struct mux_device *dev, &device_list) { |
| 801 | FOREACH(struct mux_connection *conn, &dev->connections) { | 837 | FOREACH(struct mux_connection *conn, &dev->connections) { |
| 802 | connection_teardown(conn); | 838 | connection_teardown(conn); |
| @@ -805,5 +841,7 @@ void device_shutdown(void) | |||
| 805 | collection_remove(&device_list, dev); | 841 | collection_remove(&device_list, dev); |
| 806 | free(dev); | 842 | free(dev); |
| 807 | } ENDFOREACH | 843 | } ENDFOREACH |
| 844 | pthread_mutex_unlock(&device_list_mutex); | ||
| 845 | pthread_mutex_destroy(&device_list_mutex); | ||
| 808 | collection_free(&device_list); | 846 | collection_free(&device_list); |
| 809 | } | 847 | } |
